home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
djgpp
/
go32
/
fs
/
fullscr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-23
|
194KB
|
5,686 lines
/* ---------------------------------------------------------------------- */
/* LADYBUG */
/* */
/* Copyrighted 1994-1995 by Long Doan, ld@netrix.com */
/* ---------------------------------------------------------------------- */
/* This debugger was derived from:
SALLY FULL SCREEN DEBUGGER
version 0.91a
by
Morten Welinder, terra@diku.dk
This debugger is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This debugger is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with djgpp; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ---------------------------------------------------------------------- */
#define LADYBUG_VERSION 1.02
#define MAJOR_VER 1
#define MINOR_VER 02
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <pc.h>
#include <dos.h>
#include <go32.h>
#include <dpmi.h>
#include <keys.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <setjmp.h>
#define far
#include "ed.h"
#include "debug.h"
#include "syms.h"
#include "paging.h"
#include "unassmbl.h"
#include "npx.h"
#include "serial.h"
#include "fsfuncts.h"
#include "xsupport.h"
#include "perform.h"
#include "io.h"
/* END_OF_INCLUDES */
/* ----------------------------------------------------------------------
- Information about the initialization state of the debugger. Actually
- I'm not sure that longjmp should ever be permitted.
---------------------------------------------------------------------- */
int can_longjmp = 0;
jmp_buf debugger_jmpbuf;
/* ----------------------------------------------------------------------
- Information added to use com port - by Long Doan
---------------------------------------------------------------------- */
static int using_com_port_num;
int is_in_running_mode = 0;
/* ----------------------------------------------------------------------
- Display information.
---------------------------------------------------------------------- */
int debug_screen_p;
int toplines, bottomlines;
int main_x1, main_x2, main_x3;
/* ----------------------------------------------------------------------
- Information about panes.
---------------------------------------------------------------------- */
#define PANECOUNT 11
#define CODE_PANE_NUM 0
#define REGISTER_PANE_NUM 1
#define FLAG_PANE_NUM 2
#define BREAKPOINT_PANE_NUM 3
#define DATA_PANE_NUM 4
#define NPX_PANE_NUM 5
#define STACK_PANE_NUM 6
#define INFO_PANE_NUM 7
#define WHEREIS_PANE_NUM 8
#define MODULE_PANE_NUM 9
#define HELP_PANE_NUM 10
static int pane, pane_positions[PANECOUNT], pane_pos;
static int pane_offset[PANECOUNT];
static word32 data_dump_origin, data_dump_last, data_dump_size;
static word32 code_dump_origin, code_dump_last;
static word32 *code_pane_pos, *stack_dump_pos;
static int stack_dump_origin, stack_dump_last, stack_dump_more;
static int breakpoint_origin;
static word32 *whereis_pane_sym;
static char **module_pane_text;
static char **help_pane_text;
static int whereis_sym_count, whereis_origin;
static int module_text_count, module_origin;
static int help_text_count, help_origin;
static int reg_pane_origin, flag_pane_origin;
static int code_pane_active;
static int npx_pane_active;
static int stack_pane_active;
static int info_pane_active;
static int whereis_pane_active;
static int module_pane_active;
static int help_pane_active;
static int running_xsupport = 0;
static char active_pane_name[20];
/* ----------------------------------------------------------------------
- Menus
---------------------------------------------------------------------- */
static MENU_ITEM File_Sub_Menu[] = {
{"Current item ", 1 , "" , 0},
{"Read/write log ~^X^F~", ITEM_TYPE, "\030\006" , 0},
{"View debug registers ", ITEM_TYPE, "" , 0},
{"Resize Screen ", ITEM_TYPE, "" , 0},
{"Monochrome Mode ~^X m~", ITEM_TYPE, "\030m" , 0},
{"Color Mode ", ITEM_TYPE, "" , 0},
{"Redirect IO ", ITEM_TYPE, "" , 0},
{"Save/load context ~^X^V~", ITEM_TYPE, "\030\026" , 0},
{"Exit ~^X^C~", ITEM_TYPE, "\030\003" , 0},
{0 , 0 , "" , 0}
};
static MENU_ITEM Pane_Sub_Menu[] = {
{"Current ", 1 , "" , 0},
{"~P~revious ", ITEM_TYPE, "p", 0},
{"~N~ext ", ITEM_TYPE, "n", 0},
{"~B~reakpoint", ITEM_TYPE, "b", 0},
{"~C~ode ", ITEM_TYPE, "c", 0},
{"~D~ata ", ITEM_TYPE, "d", 0},
{"~F~lags ", ITEM_TYPE, "f", 0},
{"~H~elp ", ITEM_TYPE, "h", 0},
{"~I~nfo ", ITEM_TYPE, "i", 0},
{"~M~odule ", ITEM_TYPE, "m", 0},
{"Np~X~ ", ITEM_TYPE, "x", 0},
{"~R~egisters ", ITEM_TYPE, "r", 0},
{"~S~tack ", ITEM_TYPE, "s", 0},
{"~W~here-is ", ITEM_TYPE, "w", 0},
{"Resi~Z~e ", ITEM_TYPE, "z", 0},
{0 , 0 , "" , 0}
};
static MENU_ITEM Help_Sub_Menu[] = {
{"Current ", 1 , "" , 0},
{"~A~bout ", ITEM_TYPE, "a", 0},
{"~H~elp ", ITEM_TYPE, "h", 0},
{0 , 0 , "" , 0}
};
static MENU_ITEM Misc_Sub_Menu[] = {
{"Current ", 1 , "" , 0},
{"~U~ser screen", ITEM_TYPE, "u", 0},
{"~E~valuate ", ITEM_TYPE, "e", 0},
{"~R~efresh ", ITEM_TYPE, "r", 0},
{0 , 0 , "" , 0}
};
static MENU_ITEM Main_Menu[] = {
{"Current " , 1 , "" , 0 },
{"~F~ile " , MENU_TYPE, "f", File_Sub_Menu},
{"~P~ane " , MENU_TYPE, "p", Pane_Sub_Menu},
{"~L~ocal menu ", ITEM_TYPE, "l", 0 },
{"~M~isc " , MENU_TYPE, "m", Misc_Sub_Menu},
{"~H~elp " , MENU_TYPE, "h", Help_Sub_Menu},
{0 , 0 , "" , 0 }
};
/* ----------------------------------------------------------------------
- Odds and ends.
---------------------------------------------------------------------- */
#define MAXINSTLEN 16
static int first_step;
static int escaped, control_c, control_x;
static word32 main_entry;
static int has_npx = 1;
NPX npx; /* non-static because declared so in "npx.h" */
static char hexchars[] = "0123456789abcdef";
#define MAX_REGISTERS 75
#define SCROLL_COUNT 5
#define ACTION_HIST_SIZE 40
static word32 registers[MAX_REGISTERS];
static char last_addr[4096];
/* ----------------------------------------------------------------------
- The presentation order of registers in the register pane. The three
- tables must of course match.
---------------------------------------------------------------------- */
static char *regs_names[] = {
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
"cs", "ds", "es", "fs", "gs", "ss",
"eip", "flg" };
static word32 *regs_addr[] = {
&a_tss.tss_eax, &a_tss.tss_ebx, &a_tss.tss_ecx, &a_tss.tss_edx,
&a_tss.tss_esi, &a_tss.tss_edi, &a_tss.tss_ebp, &a_tss.tss_esp,
(word32 *)&a_tss.tss_cs, (word32 *)&a_tss.tss_ds,
(word32 *)&a_tss.tss_es, (word32 *)&a_tss.tss_fs,
(word32 *)&a_tss.tss_gs, (word32 *)&a_tss.tss_ss,
&a_tss.tss_eip, &a_tss.tss_eflags };
/* ----------------------------------------------------------------------
- g: general, !: special, s: segment, f: flags, \0: end-of-table
---------------------------------------------------------------------- */
static char regs_type[] = "ggggggg!ssssss!f";
/* ----------------------------------------------------------------------
- Breakpoint data. When breakpoints are actually put into the cpu debug
- registers, data breakpoints have first priority. Any code breakpoints
- left over are set by patching the code to contain "Int 3".
---------------------------------------------------------------------- */
typedef enum { BP_Code = 0, BP_Write = 1, BP_Read = 3 } BP_TYPE;
typedef enum { BP_Normal = 0, BP_Count = 1, BP_Condition = 2 } BP_SUB_TYPE;
typedef struct
{
word32 addr;
BP_TYPE type;
BP_SUB_TYPE sub_type;
int count;
char condition[200];
unsigned char length; /* 1, 2, or 4 bytes */
unsigned char saved;
unsigned char savedbyte; /* Patched-away byte. */
} BP_ENTRY;
static int breakpoint_count;
static BP_ENTRY *breakpoint_table;
static unsigned char int03 = 0xcc;
#define MAX_UNDO 5
typedef struct undo_data {
word32 addr;
word32 value;
int size;
} UNDO_DATA;
typedef struct {
struct undo_data data[MAX_UNDO];
int count;
void (*free_entry)(word32);
} UNDO_STRUCT;
static UNDO_STRUCT data_undo;
static UNDO_STRUCT register_undo;
static UNDO_STRUCT breakpoint_undo;
static UNDO_STRUCT npx_undo;
/* ---------------------------------------------------------------------- */
static void
test_npx (void)
{ asm ("push %eax \n\
push %ebx \n\
movl %cr0, %eax \n\
andl $0x04, %eax \n\
jnz Has_387 \n\
clts \n\
fninit \n\
movl $_npx, %eax \n\
movl $0x5a5ah, (%eax)\n\
fnstsw (%eax) \n\
cmpb $0, (%eax) \n\
jne No_387 \n\
fnstcw (%eax) \n\
movw (%eax), %bx \n\
and $0x103f, %bx \n\
cmpw $0x3f, %bx \n\
jne No_387 \n\
fld1 \n\
fldz \n\
fdiv \n\
fld %st \n\
fchs \n\
fcompp \n\
fstsw (%eax) \n\
movw (%eax), %bx \n\
sahf \n\
je No_387 \n\
Has_387: \n\
movl $1, _has_npx \n\
jmp Test_done \n\
No_387: \n\
movl $0, _has_npx \n\
Test_done: \n\
pop %ebx \n\
pop %eax "
);
}
/* ---------------------------------------------------------------------- */
static void
save_npx (void)
{
asm( "\n\
inb $0xa0,%al \n\
testb $0x20,%al \n\
jz Lfclex_done \n\
xorl %eax,%eax \n\
outb %al,$0xf0 \n\
movb $0x20,%al \n\
outb %al,$0xa0 \n\
outb %al,$0x20 \n\
Lfclex_done: \n\
movl $_npx, %eax \n\
fnsave (%eax) \n\
fwait "
);
}
/* ---------------------------------------------------------------------- */
static void
load_npx (void)
{
asm( "\n\
movl $_npx, %eax \n\
frstor (%eax) "
);
/* After line 1 */
/* movb $0,4(%eax) */
/* clear pending exceptions */
/* At least on my 486 there is no need to clear pending exceptions. */
}
/* ---------------------------------------------------------------------- */
/* Display the debugger screen (if not already displayed). */
static void
debug_screen (void)
{ if (!debug_screen_p)
{
user_screen_save = get_screen ();
if (using_com_port_num)
screen_scroll (rows);
put_screen (debug_screen_save);
debug_screen_p = 1;
}
}
/* ---------------------------------------------------------------------- */
/* Display the user screen (if not already displayed). */
static void
user_screen (void)
{ if (debug_screen_p)
{
if (using_com_port_num)
screen_scroll (rows);
else
put_screen (user_screen_save);
free (user_screen_save);
debug_screen_p = 0;
}
}
/* ---------------------------------------------------------------------- */
static void
free_do_nothing (word32 addr)
{
}
/* ---------------------------------------------------------------------- */
static void
free_breakpoint (word32 addr)
{ BP_ENTRY *bp_to_free = (BP_ENTRY *)addr;
free (bp_to_free);
}
/* ---------------------------------------------------------------------- */
static void
free_npx (word32 addr)
{ NPX *npx_to_free = (NPX *)addr;
free (npx_to_free);
}
/* ---------------------------------------------------------------------- */
static void
init_undo (UNDO_STRUCT *what_undo, void (*free_func)(word32))
{ what_undo->count = 0;
what_undo->free_entry = free_func;
}
/* ---------------------------------------------------------------------- */
static void
reinit_undo (UNDO_STRUCT *what_undo)
{ while (what_undo->count)
{ what_undo->count--;
what_undo->free_entry (what_undo->data[what_undo->count].value);
}
}
/* ---------------------------------------------------------------------- */
static void
put_undo (UNDO_STRUCT *what_undo, word32 addr, word32 val, int size)
{ if (what_undo->count == MAX_UNDO)
{ int i;
what_undo->free_entry (what_undo->data[0].value);
for (i = 1; i < what_undo->count; i++)
{ what_undo->data[i - 1].addr = what_undo->data[i].addr;
what_undo->data[i - 1].value = what_undo->data[i].value;
what_undo->data[i - 1].size = what_undo->data[i].size;
}
what_undo->count--;
}
what_undo->data[what_undo->count].addr = addr;
what_undo->data[what_undo->count].value = val;
what_undo->data[what_undo->count].size = size;
what_undo->count++;
}
/* ---------------------------------------------------------------------- */
static int
get_undo (UNDO_STRUCT *what_undo, word32 *addr, word32 *val, int *size)
{ if (what_undo->count <= 0)
return (0);
what_undo->count--;
*addr = what_undo->data[what_undo->count].addr;
*val = what_undo->data[what_undo->count].value;
*size = what_undo->data[what_undo->count].size;
return (1);
}
/* ---------------------------------------------------------------------- */
typedef enum { not, com, mul, divi, add, sub, shl, shr,
and, xor, or, land, lor, less, greater, not_equal,
less_equal, great_equal, equal} OPR_Name;
typedef struct {
char *str;
OPR_Name name;
} OPR_TYPE;
typedef struct {
OPR_TYPE *opers;
int opers_num;
} OPR_CLASS;
static OPR_TYPE opers0[] = { /* Lowest priority first */
{"||", lor },
{"&&", land },
{0 , 0 }
};
static OPR_TYPE opers1[] = {
{"==", equal },
{">=", great_equal},
{"<=", less_equal },
{"!=", not_equal },
{">" , greater },
{"<" , less },
{0 , 0 }
};
static OPR_TYPE opers2[] = {
{"|" , or },
{"^" , xor },
{"&" , and },
{0 , 0 }
};
static OPR_TYPE opers3[] = {
{">>", shr },
{"<<", shl },
{0 , 0 }
};
static OPR_TYPE opers4[] = {
{"-" , sub },
{"+" , add },
{0 , 0 }
};
static OPR_TYPE opers5[] = {
{"/" , divi },
{"*" , mul },
{0 , 0 }
};
static OPR_TYPE opers6[] = { /* Unary, left until the end. */
{"~" , com },
{"!" , not },
{0 ,0 }
};
static OPR_CLASS operators[] = {
{opers0, 2 },
{opers1, 6 },
{opers2, 3 },
{opers3, 2 },
{opers4, 2 },
{opers5, 2 },
{opers6, 2 },
{0 , 0 }
};
static char l_str[200], r_str[200];
/* ---------------------------------------------------------------------- */
static char *
i_strstr (char *s1, char *s2)
{ int i, len1, len2;
if (!s1 || !s2)
return (0);
len1 = strlen (s1);
len2 = strlen (s2);
if (!len2)
return (s1);
if (!len1 || len1 < len2)
return (0);
for (i = len1 - len2; i >= 0; i--)
if (strncmp (s1 + i, s2, len2) == 0)
return (s1 + i);
return (0);
}
/* ---------------------------------------------------------------------- */
static void
break_up (char *expr, OPR_Name *opr_num, int *found)
{ word32 pos, maxpos;
int i, j, k = 1, len = strlen(expr);
char *ptr = 0, *testptr = 0;
l_str[0] = '\0';
r_str[0] = '\0';
*found = 0;
for (i = 0; !(*found) && operators[i].opers; i++)
{ maxpos = 0;
k = 0;
for (j = 0; j < operators[i].opers_num; j++)
{ testptr = i_strstr(expr, operators[i].opers[j].str);
pos = (word32)testptr;
if (pos)
{ pos -= (word32)expr;
if (pos > maxpos)
{ maxpos = pos;
ptr = testptr;
k = j;
}
*found = 1;
}
}
}
if (*found)
{ i--;
len -= strlen (ptr);
if (len > 0)
strncpy(l_str, expr, len);
l_str[len] = 0;
len = strlen (l_str) - 1;
while (len >= 0 && l_str[len] == ' ')
l_str[len--] = 0;
ptr++;
*opr_num = operators[i].opers[k].name;
switch (*opr_num)
{
case shl:
case shr:
case land:
case lor:
case not_equal:
case less_equal:
case great_equal:
case equal:
ptr++;
break;
default:
break;
}
while (*ptr && *ptr == ' ')
ptr++;
strcpy(r_str, ptr);
}
}
/* ---------------------------------------------------------------------- */
static long
parse_expression_without_paren (int size, char *expr, int *okp)
{
long l_val, r_val, result = 0;
char *l_expr, *r_expr;
OPR_Name opr_num;
int found;
break_up(expr, &opr_num, &found);
if (found)
{ if (opr_num == divi && expr[0] == '/')
{ result = syms_name2val(expr);
if (undefined_symbol)
{ *okp = ParseError_undef;
return 0;
}
*okp = ParseError_ok;
} else
{ l_expr = strdup(l_str);
r_expr = strdup(r_str);
r_val = parse_expression_without_paren (size, r_expr, okp);
free (r_expr);
if (*okp != ParseError_ok)
{ free (l_expr);
return 0;
}
l_val = parse_expression_without_paren (size, l_expr, okp);
free (l_expr);
if (*okp != ParseError_ok)
return 0;
*okp = ParseError_ok;
switch (opr_num)
{ case not:
result = !r_val;
break;
case com:
result = ~r_val;
break;
case mul:
result = l_val * r_val;
break;
case divi:
if (r_val == 0)
{ *okp = ParseError_divzero;
return 0;
} else
result = l_val / r_val;
break;
case add:
result = l_val + r_val;
break;
case sub:
result = l_val - r_val;
break;
case shl:
result = l_val << r_val;
break;
case shr:
result = l_val >> r_val;
break;
case and:
result = l_val & r_val;
break;
case xor:
result = l_val ^ r_val;
break;
case or :
result = l_val | r_val;
break;
case land:
result = l_val && r_val;
break;
case lor:
result = l_val || r_val;
break;
case equal:
result = (l_val == r_val);
break;
case great_equal:
result = (l_val >= r_val);
break;
case less_equal:
result = (l_val <= r_val);
break;
case not_equal:
result = (l_val != r_val);
break;
case greater:
result = (l_val > r_val);
break;
case less:
result = (l_val < r_val);
break;
}
}
} else
{ result = syms_name2val(expr);
if (undefined_symbol)
{
*okp = ParseError_undef;
return 0;
}
*okp = ParseError_ok;
}
switch (size)
{ case 1:
return (short)(result & 0xff);
case 2:
return (int)(result & 0xffff);
case 4: /* Fall through */
default:
return result;
}
}
/* ---------------------------------------------------------------------- */
long
parse_expression (int size, char *expr, int *okp)
{ int len = strlen (expr);
char *new_exp1 = alloca (len * 2 + 10), *new_exp2 = alloca (len * 2 + 10);
int left_paren = 0, right_paren = 0, i, found = 1;
char lookfor = ']';
long temp_value;
*okp = ParseError_ok;
strcpy (new_exp1, expr);
while (found)
{ for (i = 0; (i < len) && (new_exp1[i] != lookfor); i++)
;
if (i == len)
i = len - 1;
if (new_exp1[i] != lookfor)
{ if (lookfor == ']')
lookfor = ')';
else
found = 0;
} else
{ right_paren = i;
if (lookfor == ']')
lookfor = '[';
else
lookfor = '(';
for (i = right_paren - 1; (i >= 0) && (new_exp1[i] != lookfor); i--)
;
if (i < 0)
i = 0;
if (new_exp1[i] != lookfor)
{ *okp = ParseError_paren;
return (0);
}
left_paren = i;
temp_value = 0;
for (i = left_paren + 1; (i < right_paren); i++, temp_value++)
new_exp2[temp_value] = new_exp1[i];
new_exp2[temp_value] = 0;
temp_value = parse_expression (size, new_exp2, okp);
if (*okp != ParseError_ok)
return (0);
if (lookfor == '[')
{ switch (new_exp1[++right_paren])
{ case 'b':
i = 1;
break;
case 'h':
i = 2;
break;
case 'f':
i = 4;
break;
default:
i = 4;
right_paren--;
break;
}
if (valid_addr (temp_value, i))
read_child (temp_value, &temp_value, i);
else
{ *okp = ParseError_addr;
return (0);
}
switch (i)
{ case 1:
temp_value &= 0x000000ff;
break;
case 2:
temp_value &= 0x0000ffff;
break;
}
}
strncpy(l_str, new_exp1, left_paren);
strcpy(r_str, new_exp1 + right_paren + 1);
l_str[left_paren] = 0;
r_str[len - right_paren + 1] = 0;
sprintf (new_exp2, "%s0x%08lx%s", l_str, temp_value, r_str);
strcpy (new_exp1, new_exp2);
len = strlen (new_exp1);
if (lookfor == '[')
lookfor = ']';
else
lookfor = ')';
}
}
return (parse_expression_without_paren (size, new_exp1, okp));
}
/* ---------------------------------------------------------------------- */
static long
read_eval (int *okp, char *starttext)
{
long result;
*okp = !read_string (starttext);
if (*okp && read_buffer[0] != '\0')
{
result = parse_expression (4, read_buffer, okp);
if (*okp == ParseError_ok)
{ *okp = 1;
return (result);
}
switch (*okp)
{ case ParseError_addr:
message (CL_Error, "Reference to an invalid address.");
break;
case ParseError_divzero:
message (CL_Error, "Divide by zero.");
break;
case ParseError_paren:
message (CL_Error, "Unbalanced [] or ().");
break;
case ParseError_syntax:
message (CL_Error, "Syntax error.");
break;
case ParseError_undef:
message (CL_Error, "Undefined symbol.");
break;
}
*okp = 0;
return (0);
}
else
return *okp = 0;
}
/* ---------------------------------------------------------------------- */
inline static int
valid_instaddr (word32 vaddr)
{
return valid_addr (vaddr, MAXINSTLEN);
}
/* ---------------------------------------------------------------------- */
/* Set physical breakpoint registers from virtual ones. */
static void
activate_breakpoints (void)
{
int b, no;
BP_ENTRY *bep;
no = 0;
edi.dr[7] = 0;
/* First handle data breakpoints. */
for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
if (no <= 3 && bep->type != BP_Code)
{
bep->saved = 0;
edi.dr[7] |= ((bep->type + ((bep->length - 1) << 2)) << (16 + 4 * no)
| (2 << (2 * no)));
edi.dr[no] = bep->addr + edi.app_base;
no++;
}
/* Now handle code breakpoint. */
for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
if (bep->type == BP_Code)
if (no <= 3)
{
bep->saved = 0;
edi.dr[7] |= ((BP_Code << (16 + 4 * no)) | (2 << (2 * no)));
edi.dr[no] = bep->addr + edi.app_base;
no++;
edi.dr[7] |= 0x00000300L; /* For 386s we set GE & LE bits. */
}
else
{
bep->saved = valid_addr (bep->addr, 1);
if (bep->saved)
{
read_child (bep->addr, &bep->savedbyte, 1);
write_child (bep->addr, &int03, 1);
}
}
}
/* ---------------------------------------------------------------------- */
/* Un-patch code. */
static void
deactivate_breakpoints (void)
{ int b;
BP_ENTRY *bep;
for (b = 0, bep = breakpoint_table; b < breakpoint_count; b++, bep++)
if (bep->saved)
write_child (bep->addr, &bep->savedbyte, 1);
}
/* ---------------------------------------------------------------------- */
static int
get_breakpoint (BP_TYPE type, int length, word32 addr)
{ int b;
for (b = 0; b < breakpoint_count; b++)
if ((breakpoint_table[b].type == type) &&
((breakpoint_table[b].length == length) || (length == -1)) &&
(breakpoint_table[b].addr == addr))
return b;
return -1;
}
/* ---------------------------------------------------------------------- */
static void
reset_breakpoint (int b)
{ BP_ENTRY *del_bp = malloc (sizeof (BP_ENTRY));
del_bp->addr = breakpoint_table[b].addr;
del_bp->type = breakpoint_table[b].type;
del_bp->length = breakpoint_table[b].length;
del_bp->sub_type = breakpoint_table[b].sub_type;
del_bp->count = breakpoint_table[b].count;
strcpy (del_bp->condition, breakpoint_table[b].condition);
put_undo (&breakpoint_undo, 1, (word32)del_bp, 1);
breakpoint_table[b] = breakpoint_table[--breakpoint_count];
breakpoint_table
= realloc (breakpoint_table, breakpoint_count * sizeof (BP_ENTRY));
}
/* ---------------------------------------------------------------------- */
static int
set_breakpoint (BP_TYPE type, int length, word32 addr)
{ int b;
b = breakpoint_count;
breakpoint_table
= realloc (breakpoint_table, ++breakpoint_count * sizeof (BP_ENTRY));
breakpoint_table[b].addr = addr;
breakpoint_table[b].type = type;
breakpoint_table[b].length = length;
breakpoint_table[b].sub_type = 0;
breakpoint_table[b].count = 0;
breakpoint_table[b].condition[0] = '\0';
return b;
}
/* ---------------------------------------------------------------------- */
static void
format_type (char *output, char *input)
{ int ok;
long temp = parse_expression (4, input, &ok);
if (ok != ParseError_ok)
temp = 4;
switch (temp)
{ case 0:
sprintf (output, "%ld (%s)", temp, "Code breakpoint");
break;
case 1:
sprintf (output, "%ld (%s)", temp, "Data-write breakpoint");
break;
case 3:
sprintf (output, "%ld (%s)", temp, "Data-read/write breakpoint");
break;
default:
sprintf (output, "%ld (%s)", temp, "Invalid breakpoint type");
break;
}
}
/* ---------------------------------------------------------------------- */
static void
format_subt (char *output, char *input)
{ int ok;
long temp = parse_expression (4, input, &ok);
if (ok != ParseError_ok)
temp = 3;
switch (temp)
{ case 0:
sprintf (output, "%ld (%s)", temp, "Normal breakpoint");
break;
case 1:
sprintf (output, "%ld (%s)", temp, "Countdown breakpoint");
break;
case 2:
sprintf (output, "%ld (%s)", temp, "Conditional breakpoint");
break;
default:
sprintf (output, "%ld (%s)", temp, "Invalid breakpoint type");
break;
}
}
/* ---------------------------------------------------------------------- */
static void
init_type (char *output, char *input, word32 addr)
{ char *temp = alloca (16);
sprintf (input, "%d", *(int *)addr);
sprintf (temp, "%08lx", *(word32 *)addr);
format_type (output, temp);
}
/* ---------------------------------------------------------------------- */
static void
init_subt (char *output, char *input, word32 addr)
{ char *temp = alloca (16);
sprintf (input, "%d", *(int *)addr);
sprintf (temp, "%08lx", *(word32 *)addr);
format_subt (output, temp);
}
/* ---------------------------------------------------------------------- */
static int
edit_breakpoint (int bp_num)
{ word32 addr;
int type = 0, sub_type = 0, count = 0, size = 4, ret = 5;
char *condition = alloca (max_cols);
static DIALOG_ITEM dialog_data[] = {
{"Address :", 0 , 50, 1, format_addr, eval_word, init_addr, editor},
{"Type :", 0 , 30, 1, format_type, eval_word, init_type, editor},
{"Class :", 0 , 30, 1, format_subt, eval_word, init_subt, editor},
{"Count :", 0 , 10, 1, format_deci, eval_word, init_deci, editor},
{"Size :", 0 , 02, 1, format_deci, eval_word, init_deci, editor},
{"Condition:", 0 , 70, 1, format_asis, eval_asis, init_asis, editor},
{0 , 0 , 0 , 0, 0 , 0 , 0 , 0 }
};
static BUTTON_ITEM button_data[] = {
{" OK ", 0, action_done},
{" Cancel ", 0, action_done},
{0 , 0, 0 }
};
addr = breakpoint_table[bp_num].addr;
type = breakpoint_table[bp_num].type;
sub_type = breakpoint_table[bp_num].sub_type;
count = breakpoint_table[bp_num].count;
size = breakpoint_table[bp_num].length;
strcpy(condition,breakpoint_table[bp_num].condition);
if (size != 1 && size != 2)
size = 4;
dialog_data[0].return_addr = (word32)&addr;
dialog_data[1].return_addr = (word32)&type;
dialog_data[2].return_addr = (word32)&sub_type;
dialog_data[3].return_addr = (word32)&count;
dialog_data[4].return_addr = (word32)&size;
dialog_data[5].return_addr = (word32)condition;
dialog ("Edit Breakpoint", dialog_data, button_data, &ret);
if (ret == 1)
{ if (size != 1 && size != 2)
size = 4;
breakpoint_table[bp_num].addr = addr;
breakpoint_table[bp_num].type = type;
breakpoint_table[bp_num].sub_type = sub_type;
breakpoint_table[bp_num].count = count;
breakpoint_table[bp_num].length = size;
strcpy(breakpoint_table[bp_num].condition,condition);
return (0);
} else
return (1);
}
/* ---------------------------------------------------------------------- */
/* From ORIGIN skip COUNT instructions forward (positive count) or
backwards (negative count). Backwards skipping cannot be assumed to
be working 100% perfectly, but in the presense of debug information
it is probably very, very close.
This function works poorly close to the extremes of segments. */
static int
code_skip (int origin, int count)
{
int len, *next, i, j, k, instcount, done, leave;
char *state, *inst, *source;
if (count >= 0)
{ while (count-- > 0)
if (valid_instaddr (origin))
{ unassemble_proper (origin, &len);
origin += len;
} else
origin ++;
return origin;
} else
{ count = -count;
instcount = MAXINSTLEN * (count + 16) + 1;
next = alloca (instcount * sizeof (int));
memset (next, 0, instcount * sizeof (int));
state = alloca (instcount * sizeof (char));
memset (state, 0, instcount * sizeof (char));
done = 0;
do
{ for (i = 0; i < 2 * count; i++)
{ done++;
j = origin - done;
if (valid_instaddr (j))
{ inst = unassemble_proper (j, &len);
source = unassemble_source (j);
next[done] = j + len;
if (source)
{ leave = 0;
k = done;
while (j < origin && state[k] == 0 && !leave)
{ j++;
state[k--] = 2;
while (len-- > 1)
{ j++;
state[k--] = 3;
}
/* -------------------------------------------------------------------
- Since code and data is "never" mixed in 32 bit code we don't need this.
-------------------------------------------------------------------*/
#if 0
leave = (strncmp (inst, "jmp", 3) == 0
|| strncmp (inst, "ret", 3) == 0
|| strncmp (inst, "iret", 4) == 0);
#endif
if (!leave)
inst = unassemble_proper (j, &len);
}
}
} else
{ state[done] = 2;
next[done] = j + 1;
}
}
j = 1;
k = count;
while (k > 0 && j <= done && state[j] >= 2)
if (state[j++] == 2)
k--;
} while (k > 0 && done + 2 * count <= instcount);
if (k == 0)
return origin - j + 1;
else
{ i = origin;
k = 0;
while (count > 0 && k <= done)
{ leave = 0;
j = MAXINSTLEN;
while (!leave && j > 1)
if (j + k <= done && next[j + k] == i)
leave = 1;
else
j--;
if (!leave)
i--, k++;
else
i -= j, k += j;
count--;
/* -------------------------------------------------------------------
- If there is a source line, that also counts toward the number of lines
------------------------------------------------------------------- */
source = unassemble_source (i);
if (source)
count--;
}
return i;
}
}
}
/* ---------------------------------------------------------------------- */
static void
code_pane_goto (word32 v)
{ int i = 0;
if (v >= code_dump_origin && v <= code_dump_last)
{ while (code_pane_pos[i] < v)
i++;
if (code_pane_pos [i] == code_pane_pos[i+1])
i++;
} else
{ code_dump_origin = v;
if (valid_instaddr (v) && unassemble_source (v))
i++;
}
if (pane == 0)
pane_pos = i;
else
pane_positions[0] = i;
}
/* ---------------------------------------------------------------------- */
inline static void
go (int bp)
{
/* ------------------------------------------------------------
- These modifications cannot be undone after run/trace/step
------------------------------------------------------------ */
reinit_undo (&data_undo);
reinit_undo (®ister_undo);
reinit_undo (&npx_undo);
if (bp)
activate_breakpoints ();
is_in_running_mode = 1;
run_child ();
is_in_running_mode = 0;
if (bp)
deactivate_breakpoints ();
}
/* ---------------------------------------------------------------------- */
static void
trace_over_bp (void)
{ int len;
char *inst;
word32 old_addr = a_tss.tss_eip;
inst = unassemble_proper (old_addr, &len);
if (strcmp (inst, "popf") == 0 || strcmp (inst, "pushf") == 0)
{ edi.dr[7] = 0;
edi.dr[7] |= ((BP_Code << 16) | 2);
edi.dr[0] = old_addr + len + edi.app_base;
edi.dr[7] |= 0x00000300L;
is_in_running_mode = 1;
run_child ();
is_in_running_mode = 0;
} else
{ a_tss.tss_eflags |= 0x0100;
edi.dr[7] = 0;
is_in_running_mode = 1;
run_child ();
is_in_running_mode = 0;
a_tss.tss_eflags &= ~0x0100;
}
}
/* ---------------------------------------------------------------------- */
static char condition[200];
/* ---------------------------------------------------------------------- */
static void
go_til_true_stop (int *terminated, int *int03hit)
{ int b, i, keep_going = 1;
while (keep_going)
{ go (1);
i = a_tss.tss_irqn;
*terminated = (i == 0x21) && (a_tss.tss_eax & 0xff00) == 0x4c00;
*int03hit = (i == 0x03) &&
(get_breakpoint (BP_Code, -1, a_tss.tss_eip - 1) != -1);
if (*terminated)
a_tss.tss_eip -= 2; /* point back to Int 21h */
else if (*int03hit)
a_tss.tss_eip--; /* point back to Int 3 */
if (*terminated)
return;
if (i == 1 || *int03hit)
{ int no;
no = -1;
for (b = 0; no == -1 && b <= 3; b++)
if ((edi.dr[6] & (1 << b)) && (edi.dr[7] & (3 << (b * 2))))
no = b;
if (no != -1)
{ b = no;
no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
((edi.dr[7] >> (18 + 4 * no)) & 3) + 1,
edi.dr[no] - edi.app_base);
if (no == -1)
{ no = b;
no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
-1, edi.dr[no] - edi.app_base);
}
}
else if (*int03hit)
no = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
if (no != -1)
{ switch (breakpoint_table[no].sub_type)
{ case 1: /* Count down */
if (breakpoint_table[no].count)
breakpoint_table[no].count--;
else
keep_going = 0;
break;
case 2: /* Conditional */
{ int ofs, satisfy;
strcpy (condition, breakpoint_table[no].condition);
satisfy = parse_expression(breakpoint_table[no].length,
condition, &ofs);
if (ofs != ParseError_ok)
break;
if (satisfy != 0)
keep_going = 0;
break;
}
default:
keep_going = 0;
}
if (keep_going)
trace_over_bp ();
} else
keep_going = 0;
} else
keep_going = 0;
}
}
/* ---------------------------------------------------------------------- */
static void
step_over (int *terminated, int *int03hit, int len)
{ int b, has_break_point = 0;
word32 old_addr = 0;
int sub_type = 0, count = 0;
char *cond = 0;
b = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
if (b != -1)
{ old_addr = breakpoint_table[b].addr;
sub_type = breakpoint_table[b].sub_type;
count = breakpoint_table[b].count;
cond = strdup (breakpoint_table[b].condition);
reset_breakpoint (b);
has_break_point = 1;
}
b = set_breakpoint (BP_Code, 0, a_tss.tss_eip + len);
go_til_true_stop (terminated, int03hit);
reset_breakpoint (b);
if (has_break_point)
{ b = set_breakpoint (BP_Code, 0, old_addr);
breakpoint_table[b].sub_type = sub_type;
breakpoint_table[b].count = count;
strcpy(breakpoint_table[b].condition, cond);
free (cond);
}
}
/* ---------------------------------------------------------------------- */
static void
step (int kind)
{ int i, b, len, terminated = 0, int03hit = 0, refmem;
char *inst = 0;
switch (kind)
{ case 0:
inst = unassemble_proper (a_tss.tss_eip, &len);
if (strcmp (inst, "popf") == 0 || strcmp (inst, "pushf") == 0)
kind = 1; /* Push the right value of eflags (no trace flag). */
break;
case 1:
if (first_step)
kind = 3;
else
{ inst = unassemble_proper (a_tss.tss_eip, &len);
if (strncmp (inst, "loop", 4)
&& strncmp (inst, "call", 4)
&& strncmp (inst, "int", 3) )
kind = 0;
break;
}
}
switch (kind)
{ case 0: /* "Trace" */
a_tss.tss_eflags |= 0x0100;
edi.dr[7] = 0;
refmem = strchr (inst, '[') != 0;
if (refmem)
/* Assume that all access to code and stack segments are safe.
This should hold unless you do something extra-ordinary dirty. */
if (((a_tss.tss_ds == a_tss.tss_cs) || (a_tss.tss_ds == a_tss.tss_ss))
&& ((a_tss.tss_es == a_tss.tss_cs) || (a_tss.tss_es == a_tss.tss_ss))
&& ((a_tss.tss_fs == a_tss.tss_cs) || (a_tss.tss_fs == a_tss.tss_ss)
|| (strstr (inst, "fs:") == 0))
&& ((a_tss.tss_gs == a_tss.tss_cs) || (a_tss.tss_gs == a_tss.tss_ss)
|| (strstr (inst, "gs:") == 0)))
refmem = 0;
if (refmem)
user_screen ();
go (0);
a_tss.tss_eflags &= ~0x0100;
break;
case 1: /* "Step Over" */
user_screen ();
step_over (&terminated, &int03hit, len);
break;
case 2: /* "Run" */
user_screen ();
if (get_breakpoint (BP_Code, -1, a_tss.tss_eip) != -1)
trace_over_bp ();
go_til_true_stop (&terminated, &int03hit);
break;
case 3: /* "Run to '_main'" */
b = set_breakpoint (BP_Code, 0, main_entry);
user_screen ();
go_til_true_stop (&terminated, &int03hit);
reset_breakpoint (b);
break;
}
a_tss.tss_eflags &= ~0x0100; /* Clear TF, in case it's set by Ctrl-C */
/* (in remote debugging.) */
code_pane_goto (a_tss.tss_eip);
debug_screen ();
if (kind)
re_start_transfer ();
redraw (0);
first_step = 0;
i = a_tss.tss_irqn;
if (terminated)
{ message (CL_Msg, "Program terminated normally, exit code is %d",
(word8)a_tss.tss_eax);
} else
if (i == 1 || int03hit)
{ int no;
no = -1;
for (b = 0; no == -1 && b <= 3; b++)
if ((edi.dr[6] & (1 << b)) && (edi.dr[7] & (3 << (b * 2))))
no = b;
if (no != -1)
no = get_breakpoint ((edi.dr[7] >> (16 + 4 * no)) & 3,
((edi.dr[7] >> (18 + 4 * no)) & 3) + 1,
edi.dr[no] - edi.app_base);
else if (int03hit)
no = get_breakpoint (BP_Code, -1, a_tss.tss_eip);
if (no == -1)
if (i == 1)
no = get_breakpoint(BP_Code, -1, a_tss.tss_eip);
if ((no != -1) && (kind > 0))
{ message (CL_Info, "%s %s breakpoint at %08lx triggered.",
(breakpoint_table[no].sub_type == 0) ? "Normal" :
((breakpoint_table[no].sub_type == 1) ? "Count-down" :
"Conditional"),
(breakpoint_table[no].type == BP_Code) ? "code" :
((breakpoint_table[no].type == BP_Write) ? "data write" :
"data read/write"),
breakpoint_table[no].addr);
}
} else
{ if (i == 0x79)
message (CL_Info, "Keyboard interrupt");
else if (i == 0x09)
message (CL_Info, "Ctrl-C pressed (exception 0x09)");
else if (i == 0x75)
{ char *reason;
save_npx ();
if ((npx.status & 0x0241) == 0x0241)
reason = "stack overflow";
else if ((npx.status & 0x0241) == 0x0041)
reason = "stack underflow";
else if (npx.status & 1)
reason = "invalid operation";
else if (npx.status & 2)
reason = "denormal operand";
else if (npx.status & 4)
reason = "divide by zero";
else if (npx.status & 8)
reason = "overflow";
else if (npx.status & 16)
reason = "underflow";
else if (npx.status & 32)
reason = "loss of precision";
else
reason = "?";
message (CL_Error,
"Numeric Exception (%s) at eip=0x%08lx", reason, npx.eip);
load_npx ();
}
else if (i == 8 || (i >= 10 && i <= 14))
message (CL_Error, "Exception %d (0x%02x) occurred, error code=%#lx",
i, i, a_tss.tss_error);
else
message (CL_Error, "Exception %d (0x%02x) occurred", i, i);
}
}
/* ---------------------------------------------------------------------- */
static void
draw_debug_frames (void)
{ frame (0, 1, main_x1, toplines + 1, active_pane_name);
frame (main_x2, 1, cols - 1, toplines + 1, 0);
frame (main_x1, 1, main_x2, toplines + 1, 0);
frame (main_x3, toplines + 1, cols - 1, rows - 2, 0);
frame (0, toplines + 1, main_x3, rows - 2, 0);
if (!using_com_port_num)
{ put (main_x2, 1, "┬");
put (main_x2, toplines + 1, "┴");
put (0, toplines + 1, "├");
put (cols - 1, toplines + 1, "┤");
put (main_x1, 1, "┬");
put (main_x1, toplines + 1, "┴");
put (main_x3, toplines + 1, "┬");
put (main_x3, rows - 2, "┴");
}
}
/* ---------------------------------------------------------------------- */
static void
draw_focused_frame (void)
{ int x1, x2, y1, y2;
screen_attr = screen_attr_ffocus;
switch (pane) /* Set focused pane */
{ case 1: /* Top middle */
x1 = main_x1;
x2 = main_x2;
y1 = 1;
y2 = toplines + 1;
break;
case 2: /* Top right */
x1 = main_x2;
x2 = cols - 1;
y1 = 1;
y2 = toplines + 1;
break;
case 3: /* Bottom right */
x1 = main_x3;
x2 = cols - 1;
y1 = toplines + 1;
y2 = rows - 2;
break;
case 4: /* Bottom left */
x1 = 0;
x2 = main_x3;
y1 = toplines + 1;
y2 = rows - 2;
break;
default: /* Top left */
x1 = 0;
x2 = main_x1;
y1 = 1;
y2 = toplines + 1;
break;
}
if (pane < 1 || pane > 4)
double_frame (x1, y1, x2, y2, active_pane_name);
else
double_frame (x1, y1, x2, y2, 0);
screen_attr = screen_attr_normal;
}
/* ---------------------------------------------------------------------- */
static void
put_redraw (int x, int y, int width, int max_y, int offset, char *buf)
{ int buflen;
buflen = strlen (buf);
if (y <= max_y)
putl (x, y, width, buf + ((offset < buflen) ? offset : buflen));
}
/* ---------------------------------------------------------------------- */
void
redraw_registers (char *buf)
{ int reg, x = main_x1 + 1, y = 2, width = main_x2 - main_x1 - 1;
for (reg = reg_pane_origin; regs_type[reg]; reg++)
{ if (regs_type[reg] == 's')
sprintf (buf, " %s %04x", regs_names[reg],
*(unsigned short *)(regs_addr[reg]));
else
sprintf (buf, "%s %08lx", regs_names[reg], *(regs_addr[reg]));
put_redraw (x, y++, width, toplines,
pane_offset[REGISTER_PANE_NUM], buf);
if (y > toplines)
break;
}
while (y <= toplines)
putl (x, y++, width, " ");
if (pane == REGISTER_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
highlight (main_x1 + 1, pane_pos + 2,
main_x2 - main_x1 - 1);
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_flags (char *buf)
{ int f, x = main_x2 + 1, y = 2, width = cols - main_x2 - 2;
static char flags[] = "c?p?a?zn?ido????";
for (f = flag_pane_origin; flags[f]; f++)
{ if (flags[f] != '?')
{ sprintf (buf, "%c=%d", flags[f], (int)((a_tss.tss_eflags >> f) & 1));
put_redraw (x, y++, width, toplines, pane_offset[FLAG_PANE_NUM], buf);
}
if (y > toplines)
break;
}
while (y <= toplines)
putl (x, y++, width, " ");
if (pane == FLAG_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
highlight (main_x2 + 1, pane_pos + 2,
cols - main_x2 - 2);
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_breakpoints (char *buf)
{ int b, x = main_x3 + 1, y = toplines + 2, width = cols - main_x3 - 2;
char *name;
int32 delta;
for (b = breakpoint_origin;
b < breakpoint_origin + bottomlines / 2 && b < breakpoint_count;
b++)
{ switch (breakpoint_table[b].type)
{ case BP_Code:
sprintf (buf, "%-20s", "C ");
break;
case BP_Write:
sprintf (buf, "%-20s, %d","DW",
breakpoint_table[b].length);
break;
case BP_Read:
sprintf (buf, "%-20s, %d","DR",
breakpoint_table[b].length);
break;
}
switch (breakpoint_table[b].sub_type)
{ case 0:
sprintf (buf + 3, "Norm.");
break;
case 1:
sprintf (buf + 3, "Count");
break;
case 2:
sprintf (buf + 3, "Cond.");
break;
}
buf[8] = ' ';
putl (x, y, width, buf);
screen_attr = screen_attr_addr;
sprintf(buf, "%08lx", breakpoint_table[b].addr);
if (width > 12)
putl(x + 12, y, width - 12 > 8 ? 8 : width - 12, buf);
y++;
screen_attr = screen_attr_normal;
name = syms_val2name (breakpoint_table[b].addr, &delta);
if (name[0] != '0')
if (delta && strlen (name) < width)
sprintf (buf, " %s+%#lx", name, delta);
else
sprintf (buf, " %-*s", width, name);
else
buf[0] = '\0';
put_redraw (x, y++, width, rows,
pane_offset[BREAKPOINT_PANE_NUM], buf);
}
if (breakpoint_count == 0)
putl (x, y++, width, "No breakpoints");
while (y < rows - 2)
putl (x, y++, width, "");
if (pane == BREAKPOINT_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (breakpoint_origin >= breakpoint_count)
breakpoint_origin = breakpoint_count ? breakpoint_count - 1 : 0;
if (breakpoint_origin + pane_pos >= breakpoint_count)
pane_pos = breakpoint_count - breakpoint_origin;
if (2 * pane_pos + 2 > bottomlines)
pane_pos = bottomlines / 2 - 1;
if (pane_pos < 0)
pane_pos = 0;
else
{ highlight (main_x3 + 1, toplines + 2 + 2 * pane_pos,
cols - main_x3 - 2);
if (2 * pane_pos + 1 < bottomlines)
highlight (main_x3 + 1, toplines + 3 + 2 * pane_pos,
cols - main_x3 - 2);
}
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_data (char *buf)
{ word32 p = data_dump_origin;
int b, x, y = toplines + 2, ok, width = main_x3 - 1;
unsigned char data[8], xpos[8];
int buflen;
for (x = 0; x < 8; x++)
xpos[x] = 1 + ((data_dump_size == 1) ? (x * 3) :
((data_dump_size == 2) ? ((x / 2) * 5 + (~x & 1) * 2) :
((x / 4) * 9 + (~x & 3) * 2)));
while (y < rows - 2)
{ if ((ok = valid_addr (p, 8)))
read_child (p, data, 8);
screen_attr = screen_attr_addr;
sprintf (buf, "%08lx:",p);
putl (1, y, 9, buf);
sprintf (buf, "%70s", " ");
for (x = 0; x < 8; x++)
if (ok || valid_addr (p + x, 1))
{ if (!ok)
read_child (p + x, data + x, 1);
buf[xpos[x]] = hexchars[data[x] >> 4];
buf[xpos[x] + 1] = hexchars[data[x] & 0xf];
buf[28 + x] = (data[x] ? data[x] : '.');
} else
buf[xpos[x]] = buf[xpos[x + 1]] = buf[28 + x] = '?';
screen_attr = screen_attr_normal;
buflen = strlen (buf);
putl (10, y, width - 9, buf + ((pane_offset[DATA_PANE_NUM] < buflen)
? pane_offset[DATA_PANE_NUM] : buflen));
screen_attr = screen_attr_break;
for (x = 0; x < 8; x++)
for (b = 0; b < breakpoint_count; b++)
if (breakpoint_table[b].type != BP_Code
&& p + x >= breakpoint_table[b].addr
&& p + x < (breakpoint_table[b].addr
+ breakpoint_table[b].length))
{ if (xpos[x] >= pane_offset[DATA_PANE_NUM])
highlight (xpos[x] + 10 - pane_offset[DATA_PANE_NUM], y, 2);
if (x + 28 >= pane_offset[DATA_PANE_NUM])
highlight (38 + x - pane_offset[DATA_PANE_NUM], y, 1);
}
screen_attr = screen_attr_normal;
p += 8;
y++;
}
data_dump_last = p - 1;
if (pane == DATA_PANE_NUM)
{ int offset;
int x = pane_pos & 7, y = pane_pos >> 3;
while (y >= bottomlines)
{ y--;
pane_pos -= 8;
}
screen_attr = screen_attr_focus;
if ((38 + x + data_dump_size <= main_x3) &&
(x + 28 >= pane_offset[INFO_PANE_NUM]))
highlight (38 + x - pane_offset[DATA_PANE_NUM],
toplines + 2 + y, data_dump_size);
switch (data_dump_size)
{ case 1:
offset = 1 + 3 * x - pane_offset[DATA_PANE_NUM];
if (13 + 3 * x <= main_x3)
if (offset >= 0)
highlight (11 + 3 * x - pane_offset[DATA_PANE_NUM],
toplines + 2 + y, 2);
else if (offset > -1)
highlight (10, toplines + 2 + y, 2 + offset);
break;
case 2:
offset = 1 + 5 * (x >> 1) - pane_offset[DATA_PANE_NUM];
if (15 + 5 * (x >> 1) <= main_x3)
if (offset >= 0)
highlight (11 + 5 * (x >> 1) - pane_offset[DATA_PANE_NUM],
toplines + 2 + y, 4);
else if (offset > -4)
highlight (10, toplines + 2 + y, 4 + offset);
break;
case 4:
offset = 1 + 9 * (x >> 2) - pane_offset[DATA_PANE_NUM];
if (19 + 9 * (x >> 2) <= main_x3)
if (offset >= 0)
highlight (11 + 9 * (x >> 2) - pane_offset[DATA_PANE_NUM],
toplines + 2 + y, 8);
else if (offset > -8)
highlight (10, toplines + 2 + y, 8 + offset);
break;
}
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_code (char *buf)
{ word32 p = code_dump_origin, width = main_x1 - 1;
int y = 2, len, source = 0, buflen;
char *txt;
while (y <= toplines)
{ source = !source;
code_pane_pos[y - 2] = p;
if (source)
{ txt = unassemble_source (p);
if (txt)
{ screen_attr = screen_attr_source;
buflen = strlen (txt);
putl (1, y++, width, txt + ((pane_offset[CODE_PANE_NUM] < buflen)
? pane_offset[CODE_PANE_NUM] : buflen));
}
} else
{ int temp_len;
if (valid_instaddr (p))
txt = unassemble_proper (p, &len);
else
txt = "?", len = 1;
sprintf (buf, "%08lx%c", p, p == a_tss.tss_eip ? '>' : ' ');
screen_attr = (get_breakpoint (BP_Code, -1, p) == -1
? screen_attr_addr : screen_attr_break);
temp_len = strlen(buf);
putl (1, y++, (width > temp_len ? temp_len : width), buf);
if (width > temp_len)
{ screen_attr = (get_breakpoint (BP_Code, -1, p) == -1
? screen_attr_asm : screen_attr_break);
buflen = strlen (txt);
putl(temp_len + 1,y - 1,(width - temp_len),
txt + ((pane_offset[CODE_PANE_NUM] < buflen)
? pane_offset[CODE_PANE_NUM] : buflen));
}
p += len;
}
}
code_pane_pos[y - 2] = p + 1;
code_dump_last = p - 1;
if (pane == CODE_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
highlight (1, pane_pos + 2, main_x1 - 1);
}
screen_attr = screen_attr_normal;
}
/* ---------------------------------------------------------------------- */
void
redraw_npx (char *buf)
{ int i, y = 2, width = main_x1 - 1;
static char *rtype[] = { "Near", "-Inf", "+Inf", "Zero" };
save_npx ();
sprintf (buf,
"Control: %04lx PR=%s UN=%s OV=%s ZD=%s DN=%s IV=%s Rnd=%s",
npx.control & 0xffff,
(npx.control & (1 << 5)) ? "N" : "Y",
(npx.control & (1 << 4)) ? "N" : "Y",
(npx.control & (1 << 3)) ? "N" : "Y",
(npx.control & (1 << 2)) ? "N" : "Y",
(npx.control & (1 << 1)) ? "N" : "Y",
(npx.control & (1 << 0)) ? "N" : "Y",
rtype[(npx.control >> 10) & 3]);
put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
sprintf (buf,
"Status: %04lx PR=%s UN=%s OV=%s ZD=%s DN=%s IV=%s ST=%s",
npx.status & 0xffff,
(npx.status & (1 << 5)) ? "Y" : "N",
(npx.status & (1 << 4)) ? "Y" : "N",
(npx.status & (1 << 3)) ? "Y" : "N",
(npx.status & (1 << 2)) ? "Y" : "N",
(npx.status & (1 << 1)) ? "Y" : "N",
(npx.status & (1 << 0)) ? "Y" : "N",
(npx.status & (1 << 6)) ? "Y" : "N");
put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
sprintf (buf, "%19sC3=%d C2=%d C1=%d C0=%d",
"",
(npx.status & (1 << 14)) != 0,
(npx.status & (1 << 10)) != 0,
(npx.status & (1 << 9)) != 0,
(npx.status & (1 << 8)) != 0);
put_redraw (1, y++, width, toplines, pane_offset[NPX_PANE_NUM], buf);
for (i = 0; i < 8; i++)
{
/* ---------------------------------------------------------------------
- We assume that `long double' is the same type as npx.reg[i].
- It would be sensible to check that the sizes match, but they
- don't! For alignment reasons, `sizeof (long double)' is 12.
---------------------------------------------------------------------*/
long double d;
int tag;
int tos = (npx.status >> 11) & 7;
int exp = (int)npx.reg[i].exponent - 16382;
char *dstr = alloca (30);
dstr[0] = (npx.reg[i].sign) ? '-' : '+';
dstr[1] = '\0';
tag = (npx.tag >> (((i + tos) & 7) * 2)) & 3;
switch (tag)
{ case 0:
if (abs (exp) < 1000)
{ d = *((long double*)(npx.reg + i));
/* --------------------------------------------------------------------
- sprintf does not (djgpp 1.11m3) handle long doubles.
-------------------------------------------------------------------- */
sprintf(dstr,"%+.16g", (double) d);
} else
sprintf (dstr, "Valid, %s, and %s",
npx.reg[i].sign ? "negative" : "positive",
exp > 0 ? "huge" : "tiny");
break;
case 1:
strcat (dstr, "Zero");
break;
case 2:
if (npx.reg[i].exponent == 0x7fff)
if (npx.reg[i].sig3 == 0x8000 && npx.reg[i].sig2 == 0x0000
&& npx.reg[i].sig1 == 0x0000 && npx.reg[i].sig0 == 0x0000)
strcat (dstr, "Inf");
else
strcat (dstr, "NaN");
else
sprintf (dstr, "Special");
break;
case 3:
sprintf (dstr, "Empty");
break;
}
sprintf (buf, "st(%d): %d %04x %04x%04x%04x%04x %s",
i,
npx.reg[i].sign, npx.reg[i].exponent,
npx.reg[i].sig3, npx.reg[i].sig2,
npx.reg[i].sig1, npx.reg[i].sig0,
dstr);
put_redraw (1, y++, width, toplines,
pane_offset[NPX_PANE_NUM], buf);
if (y > toplines)
break;
}
while (y <= toplines)
putl (1, y++, width, " ");
load_npx ();
if (pane == NPX_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
highlight (1, pane_pos + 2, main_x1 - 1);
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_stack (char *buf)
{ int line, y = 2, no = -stack_dump_origin, width = main_x1 - 1;
unsigned char eipcode[4];
word32 delta, v = a_tss.tss_ebp;
word32 vaddr = a_tss.tss_eip;
int first = 1;
stack_dump_more = 0;
while (valid_instaddr (vaddr))
{ if (no++ >= 0)
if (y >= toplines)
{ stack_dump_more = 1;
break;
} else
{ char *symaddr, *sourceaddr, *sourcefile;
int len;
char *mybuf;
symaddr = syms_val2name (vaddr, &delta);
sourcefile = syms_val2line (vaddr, &line, 0);
if (sourcefile)
sprintf (sourceaddr = alloca (cols + strlen (sourcefile)),
", line %d in file %s", line, sourcefile);
else if (delta)
sprintf (sourceaddr = alloca (cols), "%+ld", (long) delta);
else
sourceaddr = "";
len = 15 + strlen (symaddr) + strlen (sourceaddr);
mybuf = alloca (len + 15);
sprintf (mybuf, "%08lx: %s%s", vaddr, symaddr, sourceaddr);
stack_dump_last = (y - 2) / 2;
stack_dump_pos[stack_dump_last] = vaddr;
put_redraw (1, y++, width, toplines,
pane_offset[STACK_PANE_NUM], mybuf);
sprintf (mybuf, " Stack frame: %08lx", v);
put_redraw (1, y++, width, toplines,
pane_offset[STACK_PANE_NUM], mybuf);
}
if (first)
{ first = 0;
read_child (vaddr, eipcode, 3);
/* ---------------------------------------------------------------------
- We look directly at the bit pattern instead of using disassembly;
- the bit patterns are those generated by gcc. In general we
- cannot expect to be able to follow a non-gcc stack anyway.
--------------------------------------------------------------------- */
if ((eipcode[0] == 0x55 && eipcode[1] == 0x89 && eipcode[2] == 0xe5)
|| eipcode[0] == 0xc3)
{
/* ---------------------------------------------------------------------
- In this case where we are looking at `Push Ebp//Mov Ebp,Esp'
- or `Ret', only the return address is on the stack; I believe
- this only to happen in the innermost activation record.
--------------------------------------------------------------------- */
if (valid_addr (a_tss.tss_esp, 4))
read_child (a_tss.tss_esp, &vaddr, 4);
else
break;
} else
{ if (eipcode[0] == 0x89 && eipcode[1] == 0xe5)
/* ---------------------------------------------------------------------
- When looking at `Mov Esp,Ebp' the next stack frame is on
- the stack and pointed to by the stack pointer. We are
- actually in the same situation after `Mov Esp,Ebp' which
- is generated by gcc with the -m486 option. This case is,
- however, handled perfectly by using the base pointer.
--------------------------------------------------------------------- */
v = a_tss.tss_esp;
if (v >= a_tss.tss_esp && v < 0x80000000L && valid_addr (v, 8))
{ read_child (v + 4, &vaddr, 4);
read_child (v, &v, 4);
} else
break;
}
} else
{ if (v >= a_tss.tss_esp && v < 0x80000000L && valid_addr (v, 8))
{ read_child (v + 4, &vaddr, 4);
read_child (v, &v, 4);
} else
break;
}
}
while (y <= toplines)
putl (1, y++, width, " ");
if (pane == STACK_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos * 2 + 2 > toplines - 1)
pane_pos = (toplines - 1) / 2 - 1;
if (pane_pos < 0)
pane_pos = 0;
else
{ if (pane_pos > stack_dump_last)
pane_pos = stack_dump_last;
highlight (1, pane_pos * 2 + 2, main_x1 - 1);
}
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_info (char *buf)
{ int y = 2, width = main_x1 - 1;
long ul;
char *s = alloca (20);
_go32_dpmi_meminfo info;
_go32_dpmi_registers regs;
sprintf (buf, "Debugger version ............: %d.%02d %s",
MAJOR_VER, MINOR_VER,
MAJOR_VER == 0 ? "beta" : "");
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
_go32_dpmi_get_free_memory_information (&info);
switch (_go32_info_block.run_mode)
{ case _GO32_RUN_MODE_RAW:
sprintf (s, "Raw");
break;
case _GO32_RUN_MODE_XMS:
sprintf (s, "Xms");
break;
case _GO32_RUN_MODE_VCPI:
sprintf (s, "Vcpi");
break;
case _GO32_RUN_MODE_DPMI:
sprintf (s, "Dpmi %d.%02x",
_go32_info_block.run_mode_info >> 8,
_go32_info_block.run_mode_info & 0xff);
break;
default:
sprintf (s, "Unknown");
}
sprintf (buf, "Running mode ................: %s", s);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
if (y <= toplines)
putl (1, y++, width, "");
ul = info.total_physical_pages;
if (ul > 0)
{ ul <<= 12;
sprintf (buf, "Total physical memory .......: %lu KB", ul >> 10);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
}
ul = info.available_physical_pages
? info.available_physical_pages << 12
: info.available_memory;
sprintf (buf, "Remaining physical memory ...: %lu KB", ul >> 10);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
ul = info.available_memory;
sprintf (buf, "Remaining virtual memory ....: %lu KB", ul >> 10);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
ul = info.free_linear_space << 12;
if (ul >= 0)
{ sprintf (buf, "Free linear space ...........: %ld KB", ul >> 10);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
}
/* ----------------------------------------------------------------
- Remember that Dos memory is only made available of direct request;
- using 0xffff does not count as a request.
---------------------------------------------------------------- */
regs.h.ah = 0x48;
regs.x.bx = 0xffff;
regs.x.ss = regs.x.sp = 0;
/* ----------------------------------------------------------
- The call _go32_dpmi_simulate_int () causes the program
- to hang under XMS mode.
---------------------------------------------------------- */
if (_go32_info_block.run_mode != _GO32_RUN_MODE_XMS)
_go32_dpmi_simulate_int (0x21, ®s);
ul = regs.x.bx << 4;
sprintf (buf, "Free dos memory .............: %ld %s",
ul > 8192 ? ul >> 10 : ul,
ul > 8192 ? "KB" : "Bytes");
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
if (y <= toplines)
putl (1, y++, width, "");
sprintf (buf, "Ctrl-C checking .............: %s",
getcbrk () ? "On" : "Off");
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
if (y <= toplines)
putl (1, y++, width, "");
sprintf (buf, "Program text ................: %08lx - %08lx",
areas[A_text].first_addr, areas[A_text].last_addr);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
sprintf (buf, "Program data ................: %08lx - %08lx",
areas[A_data].first_addr, areas[A_data].last_addr);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
sprintf (buf, "Program bss .................: %08lx - %08lx",
areas[A_bss].first_addr, areas[A_bss].last_addr);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
sprintf (buf, "Program stack ...............: %08lx - %08lx",
areas[A_stack].first_addr, areas[A_stack].last_addr);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
if (y <= toplines)
putl (1, y++, width, "");
sprintf (buf, "Using com port number .......: %d",
using_com_port_num);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
sprintf (buf, "Using symbol file ...........: %s%s.%s",
sympath, symname, symext);
put_redraw (1, y++, width, toplines, pane_offset[INFO_PANE_NUM], buf);
while (y <= toplines)
putl (1, y++, width, " ");
}
/* ---------------------------------------------------------------------- */
void
redraw_whereis (char *buf)
{ int y = 2, width = main_x1 - 1, i = whereis_origin;
char *s;
while (y <= toplines)
if (i < whereis_sym_count)
{ s = syms_makewild (whereis_pane_sym[i++]);
put_redraw (1, y++, width, toplines,
pane_offset[WHEREIS_PANE_NUM], s);
} else
putl (1, y++, width, " ");
if (pane == WHEREIS_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
if (whereis_sym_count)
highlight (1, pane_pos + 2, main_x1 - 1);
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_module (char *buf)
{ int y = 2, width = main_x1 - 1, i = module_origin;
while (y <= toplines)
if (i < module_text_count)
put_redraw (1, y++, width, toplines,
pane_offset[MODULE_PANE_NUM], module_pane_text[i++]);
else
putl (1, y++, width, " ");
if (pane == MODULE_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
if (module_text_count)
highlight (1, pane_pos + 2, main_x1 - 1);
screen_attr = screen_attr_normal;
}
}
/* ---------------------------------------------------------------------- */
void
redraw_help (char *buf)
{ int y = 2, width = main_x1 - 1, i = help_origin;
while (y <= toplines)
if (i < help_text_count)
{ screen_attr = ((*help_pane_text[i] != ' ')
? screen_attr_help : screen_attr_normal);
put_redraw (1, y++, width, toplines,
pane_offset[HELP_PANE_NUM], help_pane_text[i++]);
} else
putl (1, y++, width, " ");
if (pane == HELP_PANE_NUM)
{ screen_attr = screen_attr_focus;
if (pane_pos >= toplines - 1)
pane_pos = toplines - 2;
if (help_text_count)
highlight (1, pane_pos + 2, main_x1 - 1);
screen_attr = screen_attr_normal;
}
}
/* --
static char *st_fmt = "%04x %04x %04x %04x %04x %04x %08lx %08lx";
-- */
/* ---------------------------------------------------------------------- */
void
redraw (int first)
{ char *buf = alloca (1024);
debug_screen ();
screen_attr = ScreenAttrib = screen_attr_normal;
if (first == -1)
{ screen_attr = screen_attr_resize;
clear_screen();
}
draw_debug_frames ();
if (first == -1) /* For resizing */
{ put_screen (debug_screen_save);
return;
}
draw_focused_frame ();
redraw_registers (buf);
redraw_flags (buf);
redraw_breakpoints (buf);
redraw_data (buf);
if (code_pane_active)
redraw_code (buf);
if (npx_pane_active)
redraw_npx (buf);
if (stack_pane_active)
redraw_stack (buf);
if (info_pane_active)
redraw_info (buf);
if (whereis_pane_active)
redraw_whereis (buf);
if (module_pane_active)
redraw_module (buf);
if (help_pane_active)
redraw_help (buf);
screen_attr = st_ln_attr;
/* --
asm ("push %ebp \n\
push %esp \n\
push %ss \n\
push %gs \n\
push %fs \n\
push %es \n\
push %ds \n\
push %cs \n\
push _st_fmt \n\
push $_StatusLine \n\
call _sprintf \n\
add $0x28, %esp \n\
");
st_fmt[0] += 0;
-- */
putl (0, rows - 1, cols, StatusLine);
if (running_xsupport)
redraw_xsupport (buf);
else
show_menu_bar (Main_Menu);
free (buf);
}
/* ---------------------------------------------------------------------- */
static void
init_module (void)
{
char *s;
s = malloc(25);
s = "Modules listing:";
module_pane_text = realloc (module_pane_text,
(++module_text_count) * sizeof (char *));
module_pane_text[module_text_count - 1] = strdup (s);
free(s);
s = get_module(module_text_count - 1);
while (!undefined_symbol)
{
module_pane_text = realloc (module_pane_text,
(++module_text_count) * sizeof (char *));
module_pane_text[module_text_count - 1] = strdup (s);
free(s);
s = get_module(module_text_count - 1);
}
undefined_symbol = 0;
}
/* ---------------------------------------------------------------------- */
static void
put_help_line(const char *str)
{
help_pane_text = realloc (help_pane_text,
(++help_text_count) * sizeof (char *));
help_pane_text[help_text_count - 1] = strdup (str);
}
/* ---------------------------------------------------------------------- */
static void
init_help (void)
{ put_help_line("----------------------------------------------------------");
put_help_line("GLOBAL KEY BINDINGS:");
put_help_line(" ");
put_help_line(" C-x C-c Quit debugger. You will be prompted first.");
put_help_line(" C-x C-v Save or load debugger context.");
put_help_line(" C-r Run program.");
put_help_line(" C-h Make Help pane active.");
put_help_line(" BS Make Help pane active.");
put_help_line(" C-x C-w Write active pane contents to a file. Only");
put_help_line(" the visible portion of the pane is saved.");
put_help_line(" C-x C-f Display contents of log file.");
put_help_line(" C-x m Toggle between color/monochrome mode.");
put_help_line(" C-x C-e Evaluate an expression and display result");
put_help_line(" in the minibuffer.");
put_help_line(" C-z Show program output. Press any key to return");
put_help_line(" to the debugger.");
put_help_line(" C-l Redraw the screen.");
put_help_line(" ESC C-p <c> Goto pane whose name begins with <c>.");
put_help_line(" C-x C-o Toggle between insert/overstrike mode.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("MAIN MENU:");
put_help_line(" ");
put_help_line(" ESC ESC Quit main menu, go to previously active pane.");
put_help_line(" C-g Quit main menu, go to previously active pane.");
put_help_line(" f Select File pulldown.");
put_help_line(" p Select Pane pulldown.");
put_help_line(" l Select Local pulldown.");
put_help_line(" m Select Miscellaneous pulldown.");
put_help_line(" h Select Help pulldown.");
put_help_line(" CR Select pulldown of highlighted choice.");
put_help_line(" DN Select pulldown of highlighted choice.");
put_help_line(" C-n Select pulldown of highlighted choice.");
put_help_line(" C-f Highlight next choice on main menu.");
put_help_line(" TAB Highlight next choice on main menu.");
put_help_line(" RT Highlight next choice on main menu.");
put_help_line(" C-b Highlight previous choice on main menu.");
put_help_line(" S-TAB Highlight previous choice on main menu.");
put_help_line(" LT Highlight previous choice on main menu.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("PULLDOWNS:");
put_help_line(" ");
put_help_line(" ESC ESC Go to main menu.");
put_help_line(" CR Select currently highlighted pulldown item.");
put_help_line(" C-n Highlight next pulldown item.");
put_help_line(" DN Highlight next pulldown item.");
put_help_line(" C-p Highlight previous pulldown item.");
put_help_line(" UP Highlight previous pulldown item.");
put_help_line(" C-f Show pulldown of next main menu choice.");
put_help_line(" RT Show pulldown of next main menu choice.");
put_help_line(" TAB Show pulldown of next main menu choice.");
put_help_line(" C-b Show pulldown of previous main menu choice.");
put_help_line(" LT Show pulldown of previous main menu choice.");
put_help_line(" S-TAB Show pulldown of previous main menu choice.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("PANES:");
put_help_line(" ");
put_help_line(" ESC ESC Go to main menu.");
put_help_line(" C-x o Go forward one pane.");
put_help_line(" TAB Go forward one pane.");
put_help_line(" S-TAB Go backward one pane.");
put_help_line(" C-x C-x Go to previous pane (and again to return).");
put_help_line(" C-x ^ Make current pane taller by one line.");
put_help_line(" C-x } Make current pane wider by one line.");
put_help_line(" C-x > Scroll text right (show more of the left).");
put_help_line(" C-x < Scroll text left (show more of the right).");
put_help_line(" C-f Move forward one line/byte/halfword/fullword.");
put_help_line(" RT Move forward one line/byte/halfword/fullword.");
put_help_line(" C-b Move backward one line/byte/halfword/fullword.");
put_help_line(" LT Move backward one line/byte/halfword/fullword.");
put_help_line(" C-n Move forward one line.");
put_help_line(" DN Move forward one line.");
put_help_line(" C-p Move backward one line.");
put_help_line(" UP Move backward one line.");
put_help_line(" C-v Move forward one page.");
put_help_line(" PGDN Move forward one page.");
put_help_line(" M-v Move backward one page.");
put_help_line(" PGUP Move backward one page.");
put_help_line(" M-< Move to beginning of pane.");
put_help_line(" HOME Move to beginning of pane.");
put_help_line(" M-> Move to end of pane.");
put_help_line(" END Move to end of pane.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("DIALOG BOXES:");
put_help_line(" ");
put_help_line(" ESC ESC Quit dialog box and discard any changes.");
put_help_line(" C-g Quit dialog box and discard any changes.");
put_help_line(" TAB Move to next field, if applicable.");
put_help_line(" C-n Move to next field, if applicable.");
put_help_line(" DN Move to next field, if applicable.");
put_help_line(" S-TAB Move to previous field, if applicable.");
put_help_line(" C-p Move to previous field, if applicable.");
put_help_line(" UP Move to previous field, if applicable.");
put_help_line(" CR Select highlighted item, if applicable.");
put_help_line(" C-f Move forward one character, if applicable.");
put_help_line(" RT Move forward one character, if applicable.");
put_help_line(" C-b Move backward one character, if applicable.");
put_help_line(" LT Move backward one character, if applicable.");
put_help_line(" DEL Delete character left of cursor.");
put_help_line(" C-d Delete character under cursor.");
put_help_line(" CR Accept input and");
put_help_line(" - go to next field (if not on a button), or");
put_help_line(" - take action specified by button.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("MINBUFFER:");
put_help_line(" ");
put_help_line(" ESC ESC Quit minibuffer and discard any changes.");
put_help_line(" C-g Quit minibuffer and discard any changes.");
put_help_line(" C-f Move forward one character, if applicable.");
put_help_line(" RT Move forward one character, if applicable.");
put_help_line(" C-b Move backward one character, if applicable.");
put_help_line(" LT Move backward one character, if applicable.");
put_help_line(" DEL Delete character left of cursor.");
put_help_line(" C-d Delete character under cursor.");
put_help_line(" CR Accept input.");
put_help_line(" ");
put_help_line("==========================================================");
put_help_line(" PANE-SPECIFIC HELP");
put_help_line("==========================================================");
put_help_line("----------------------------------------------------------");
put_help_line("HELP PANE:");
put_help_line(" ");
put_help_line(" CR Make code pane active.");
put_help_line(" C-g Make code pane active.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("CODE PANE:");
put_help_line(" ");
put_help_line(" s Single step, stepping over function calls.");
put_help_line(" S Single step, stepping into function calls.");
put_help_line(" C-c a Animate - run program by single stepping at");
put_help_line(" a user-specified speed.");
put_help_line(" b Toggle breakpoint on/off at current location.");
put_help_line(" e Edit breakpoint via dialog box.");
put_help_line(" Breakpoint particulars are:");
put_help_line(" Address - breakpoint location.");
put_help_line(" Type - 0 == Code breakpoint.");
put_help_line(" 1 == Data write breakpoint.");
put_help_line(" 2 == Data read breakpoint.");
put_help_line(" Class - 0 == Always enabled.");
put_help_line(" 1 == Breakpoint enabled only after");
put_help_line(" being reached <count> times.");
put_help_line(" 2 == Breakpoint enabled only after");
put_help_line(" <condition> is true (nonzero).");
put_help_line(" Count - Number of hits before a class 1");
put_help_line(" breakpoint activates.");
put_help_line(" Condition - Condition to be met before a");
put_help_line(" class 2 breakpoint activates.");
put_help_line(" The condition can be almost any");
put_help_line(" C expression. For more info on");
put_help_line(" allowable expressions, see the");
put_help_line(" manual section on expressions.");
put_help_line(" Two examples are:");
put_help_line(" _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
put_help_line(" (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4");
put_help_line(" Size - The Size parameter allows you");
put_help_line(" to specify the maximum size to");
put_help_line(" be used during evaluation of");
put_help_line(" expressions.");
put_help_line(" C-c t Trace to current address. Same as toggling");
put_help_line(" breakpoint, then running program.");
put_help_line(" <n> CR Disassemble and display memory at specified");
put_help_line(" decimal address.");
put_help_line(" <x> CR Disassemble and display memory at specified");
put_help_line(" hexadecimal address.");
put_help_line(" _<sym> CR Disassemble and display memory at address");
put_help_line(" specified by symbol <sym>.");
put_help_line(" %<sym> CR Disassemble and display memory at address");
put_help_line(" specified by value in register denoted by");
put_help_line(" symbol <sym>.");
put_help_line(" <exp> CR Disassemble and display memory at address");
put_help_line(" specified by value of expression <exp>.");
put_help_line(" i Disassemble and display memory at address");
put_help_line(" specified by EIP (current run location).");
put_help_line(" C-c i Set EIP to address of currently highlighted");
put_help_line(" instruction.");
put_help_line(" p Modify performance analyzer settings.");
put_help_line(" C-c p Start performance analyzer and run program");
put_help_line(" (if performance analyzer timer has been set).");
put_help_line(" M-b Move pane's origin left by one byte.");
put_help_line(" M-f Move pane's origin right by one byte.");
put_help_line(" C-x / <c> Save highlighted location in debugger code");
put_help_line(" pane register <c>.");
put_help_line(" C-x j <c> Disassemble and display memory at location");
put_help_line(" saved in debugger code pane register <c>.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("DATA PANE:");
put_help_line(" ");
put_help_line(" w Toggle data write breakpoint on/off.");
put_help_line(" r Toggle data read/write breakpoint on/off.");
put_help_line(" e Edit data read or read/write breakpoint.");
put_help_line(" Breakpoint particulars are:");
put_help_line(" Address - breakpoint location.");
put_help_line(" Type - 0 == Code breakpoint.");
put_help_line(" 1 == Data write breakpoint.");
put_help_line(" 2 == Data read breakpoint.");
put_help_line(" Class - 0 == Always enabled.");
put_help_line(" 1 == Breakpoint enabled only after");
put_help_line(" being reached <count> times.");
put_help_line(" 2 == Breakpoint enabled only after");
put_help_line(" <condition> is true (nonzero).");
put_help_line(" Count - Number of hits before a class 1");
put_help_line(" breakpoint activates.");
put_help_line(" Condition - Condition to be met before a");
put_help_line(" class 2 breakpoint activates.");
put_help_line(" The condition can be almost any");
put_help_line(" C expression. For more info on");
put_help_line(" allowable expressions, see the");
put_help_line(" manual section on expressions.");
put_help_line(" Two examples are:");
put_help_line(" _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
put_help_line(" (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4");
put_help_line(" Size - The Size parameter allows you");
put_help_line(" to specify the maximum size to");
put_help_line(" be used during evaluation of");
put_help_line(" expressions.");
put_help_line(" b Display data in byte format.");
put_help_line(" h Display data in halfword (two byte) format.");
put_help_line(" f Display data in fullword (four byte) format.");
put_help_line(" <n> CR Display memory at specified decimal address.");
put_help_line(" <x> CR Display memory at specified hexadecimal");
put_help_line(" address.");
put_help_line(" _<sym> CR Display memory at address specified by");
put_help_line(" symbol <sym>.");
put_help_line(" %<sym> CR Display memory at address specified by value");
put_help_line(" in register denoted by symbol <sym>.");
put_help_line(" <exp> CR Display memory at address specified by value");
put_help_line(" of expression <exp>.");
put_help_line(" i Display memory at address specified by EIP");
put_help_line(" (current run location).");
put_help_line(" s Display memory at address specified by ESP");
put_help_line(" (current stack pointer).");
put_help_line(" * Dereference currently highlighted value.");
put_help_line(" @ Retrace steps after a '*' command. Up to");
put_help_line(" five (5) steps back are allowed.");
put_help_line(" n Display data in customized format.");
put_help_line(" p Input/output from/to ports as follows:");
put_help_line(" Size - 1 = byte, 2 = word, 3 = dword");
put_help_line(" b = byte, h = word, f = dword");
put_help_line(" Port - port to access");
put_help_line(" Data - data to write");
put_help_line(" <In> button - input from port");
put_help_line(" <Out> button - output to port");
put_help_line(" M-b Move pane's origin left by one byte.");
put_help_line(" M-f Move pane's origin right by one byte.");
put_help_line(" C-c m Modify memory at cursor");
put_help_line(" C-c u Undo last memory modification. No more than");
put_help_line(" five (5) modifications can be undone.");
put_help_line(" C-c s Search memory.");
put_help_line(" C-x / <c> Save highlighted location in debugger data");
put_help_line(" pane register <c>.");
put_help_line(" C-x j <c> Display memory at location saved in");
put_help_line(" debugger data pane register <c>.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("REGISTERS PANE:");
put_help_line(" ");
put_help_line(" C-c m Modify register at cursor.");
put_help_line(" C-c u Undo last register modification. No more");
put_help_line(" than five (5) modifications can be undone.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("FLAGS PANE:");
put_help_line(" ");
put_help_line(" All commands accessed via local menu.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("BREAKPOINT PANE:");
put_help_line(" ");
put_help_line(" CR Goto location of currently highlighted");
put_help_line(" breakpoint, in code or data pane, as");
put_help_line(" appropriate.");
put_help_line(" DEL Delete currently highlighted breakpoint.");
put_help_line(" C-d Delete currently highlighted breakpoint.");
put_help_line(" C-e Edit currently highlighted breakpoint.");
put_help_line(" C-k Delete from currently highlighted breakpoint");
put_help_line(" up to the last breakpoint.");
put_help_line(" C-y Restore from previous deletion. No more");
put_help_line(" than five (5) deletions can be undone.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("WHEREIS PANE:");
put_help_line(" ");
put_help_line(" CR Display data/code at address represented by");
put_help_line(" currently highlighted symbol.");
put_help_line(" _<sym> CR Find <sym> in symbol table");
put_help_line(" Permissible wildcards are:");
put_help_line(" ? - Matches one character");
put_help_line(" * - Matches any number of characters");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("MODULE PANE:");
put_help_line(" ");
put_help_line(" CR Prompt for a line number, disassemble and");
put_help_line(" display code at that location.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("NPX PANE: ");
put_help_line(" ");
put_help_line(" C-c e Empty register.");
put_help_line(" C-c n Negate register contents.");
put_help_line(" C-c z Zero register.");
put_help_line(" C-c m Modify register contents.");
put_help_line(" C-c u Undo last register modification. No more");
put_help_line(" than five (5) modifications can be undone.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("PERFORMANCE ANALYZER DATA VIEWER:");
put_help_line(" ");
put_help_line(" C-x C-w Log performance analyzer results to file.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("STACK PANE:");
put_help_line(" ");
put_help_line(" CR Select highlighted location and display");
put_help_line(" in data pane.");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("INFO PANE:");
put_help_line(" ");
put_help_line(" No commands available.");
put_help_line(" ");
put_help_line("==========================================================");
put_help_line(" SYNTAX AND VALUES");
put_help_line("==========================================================");
put_help_line("----------------------------------------------------------");
put_help_line("C EXPRESSIONS ALLOWED:");
put_help_line(" ");
put_help_line(" Syntax:");
put_help_line(" <expr> = <l_exp> [<l_op> <l_exp> ...]");
put_help_line(" <l_exp> = <a_exp> [<r_op> <a_exp> ...] | ");
put_help_line(" (<l_exp>) | !<l_exp>");
put_help_line(" <a_exp> = <a_exp>|<identifier> [<a_op> ");
put_help_line(" <a_exp>|<identifier> ...] | (<a_exp>)");
put_help_line(" <identifier> = <identifier> | <[<a_exp>]><size>");
put_help_line(" where");
put_help_line(" <l_exp> is a logical expression.");
put_help_line(" <l_op> is one of: && ||");
put_help_line(" <a_exp> is an arithmetic expression");
put_help_line(" <r_op> is one of: < <= == != >= >");
put_help_line(" <a_op> is one of: + - * / >> << & | ! ~");
put_help_line(" <identifier> is an identifiler (a symbol, register) ");
put_help_line(" a number, or a memory reference.");
put_help_line(" ");
put_help_line(" * <identifier> can be a global variable name,");
put_help_line(" symbolic constant, constant value, register name,");
put_help_line(" or memory reference (i.e. an expression which");
put_help_line(" evaluates to a memory location).");
put_help_line(" * All register names must begin with a '%' (percent) ");
put_help_line(" character. ");
put_help_line(" * All memory references have the structure: ");
put_help_line(" [<address expression>]size ");
put_help_line(" where size can be b, h, f, or nothing.");
put_help_line(" b: 1 byte. h: 2 bytes. f: 4 bytes. Any other");
put_help_line(" character immediately following the right square ");
put_help_line(" bracket (]) and is not one of the above characters");
put_help_line(" will be interpreted as part of the expression.");
put_help_line(" By default (if neither b, h, or f follows the");
put_help_line(" right square bracket,) the reference will read");
put_help_line(" 4 bytes from memory.");
put_help_line(" * When constructing expressions, be aware that");
put_help_line(" the modulo (%) operator is not allowed, since");
put_help_line(" it conficts with the register naming scheme.");
put_help_line(" To perform a modulo, use divide (/) and");
put_help_line(" subtract (-): (a % b) == (a - a / b)");
put_help_line(" * When constructing expressions, be wary");
put_help_line(" of possible overflow (the debugger uses");
put_help_line(" 32 bit arithmetic to evaluate expressions).");
put_help_line(" ");
put_help_line(" Examples of valid expressions: ");
put_help_line(" ");
put_help_line(" _Odd_num >> 3 == 1 && (_Even_num >> _Shift_val || _Test)");
put_help_line(" (([%esi + %eax * 4] & 0x5fff) >> 12) & 0x0f == 4 ");
put_help_line(" ");
put_help_line("----------------------------------------------------------");
put_help_line("REMOTE DEBUGGING DEVICES");
put_help_line(" ");
put_help_line(" con : console. ");
put_help_line(" com_one : COM1. ");
put_help_line(" com_two : COM2. ");
put_help_line(" com_three : COM3. ");
put_help_line(" com_four : COM4. ");
put_help_line(" ");
put_help_line("==========================================================");
}
/* ---------------------------------------------------------------------- */
static void
initialize (void)
{ int i;
using_com_port_num = remote;
init_io (using_com_port_num);
if (_go32_info_block.run_mode != _GO32_RUN_MODE_DPMI)
test_npx ();
debug_screen_p = 0;
toplines = (rows / 2) + 4;
bottomlines = rows - 4 - toplines;
main_x1 = cols - 18;
main_x2 = cols - 5;
main_x3 = 46;
code_pane_pos = malloc ((rows + 2) * sizeof (word32));
stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
debug_screen_save = get_screen ();
debug_screen_save[1] = debug_screen_save[2] = 0; /* Patch cursor pos. */
pane = 10;
pane_pos = 0;
for (i = 0; i < PANECOUNT; i++) pane_positions[i] = 0;
data_dump_origin = areas[A_data].first_addr;
data_dump_size = 1;
code_dump_origin = a_tss.tss_eip;
stack_dump_origin = 0;
breakpoint_origin = 0;
breakpoint_count = 0;
breakpoint_table = malloc (breakpoint_count * sizeof (BP_ENTRY));
whereis_origin = 0;
whereis_sym_count = 0;
whereis_pane_sym = malloc (whereis_sym_count * sizeof (char *));
module_origin = 0;
module_text_count = 0;
module_pane_text = malloc (module_text_count * sizeof (char *));
init_module ();
help_origin = 0;
help_text_count = 0;
help_pane_text = malloc (help_text_count * sizeof (char *));
init_help();
flag_pane_origin = 0;
reg_pane_origin = 0;
help_pane_active = 1;
npx_pane_active = stack_pane_active = info_pane_active
= whereis_pane_active = module_pane_active
= code_pane_active = 0;
sprintf (active_pane_name, "Help Pane");
init_eval_data (0, 0); /* Force to calculate addresses */
init_undo (&data_undo, free_do_nothing);
init_undo (®ister_undo, free_do_nothing);
init_undo (&npx_undo, free_npx);
init_undo (&breakpoint_undo, free_breakpoint);
redraw (1);
message (CL_Info, "Ladybug version %d.%02d", MAJOR_VER, MINOR_VER);
}
/* ---------------------------------------------------------------------- */
static void
view_eval_data (void)
{
EVAL_SEG_INFO swap_data;
EVAL_DATA_TABLE temp_data;
int i, j, percent_bar;
long percent;
int32 delta;
word32 total_hits = 0, in_hits = 0, out_hits;
char *save, *name = alloca (256), *name2 = alloca (256), *p;
if (total_hits_count == 0)
{ message (CL_Error,
"Nothing has been recorded, cannot calculate percentage");
return;
}
for (i = 0; i < EVAL_SEGMENTS; i++)
{ temp_data[i].start_addr = evaluation_data[i].start_addr;
temp_data[i].stop_addr = evaluation_data[i].stop_addr;
temp_data[i].hits_count = evaluation_data[i].hits_count;
total_hits += temp_data[i].hits_count;
}
for (i = 0; i < EVAL_SEGMENTS - 1; i++)
for (j = i + 1; j < EVAL_SEGMENTS; j++)
if (temp_data[i].hits_count < temp_data[j].hits_count)
{ swap_data.start_addr = temp_data[i].start_addr;
swap_data.stop_addr = temp_data[i].stop_addr;
swap_data.hits_count = temp_data[i].hits_count;
temp_data[i].start_addr = temp_data[j].start_addr;
temp_data[i].stop_addr = temp_data[j].stop_addr;
temp_data[i].hits_count = temp_data[j].hits_count;
temp_data[j].start_addr = swap_data.start_addr;
temp_data[j].stop_addr = swap_data.stop_addr;
temp_data[j].hits_count = swap_data.hits_count;
}
j = (rows / 2) - 4;
save = debug_screen_save;
debug_screen_save = get_screen ();
screen_attr = screen_attr_normal;
clear_screen ();
screen_attr = screen_attr_ffocus;
double_frame (0, 0, cols - 1, rows - 1, "Performance Analyzer's Result");
screen_attr = screen_attr_normal;
sprintf (name, "Most called segments (from %08lx to %08lx)",
evaluation_data[0].start_addr,
evaluation_data[EVAL_SEGMENTS - 1].stop_addr);
putl (cols / 2 - 24, 1, 50, name);
for (i = 0; i < j; i++)
in_hits += temp_data[i].hits_count;
if (in_hits == 0)
putl (2, 3, cols-5, "Nothing is recorded inside the given addresses.");
else
{ for (i = 0; i < j; i++)
{
percent = (long)temp_data[i].hits_count;
percent *= 100;
p = syms_val2name (temp_data[i].start_addr, &delta);
if (p[0] != '0')
if (delta)
sprintf (name, "(%s+%#lx)", p, delta);
else
sprintf (name, "(%s)",p);
else
sprintf(name, "(No Symbols");
p = syms_val2name (temp_data[i].stop_addr, &delta);
if (p[0] != '0')
if (delta)
sprintf (name2, "(%s+%#lx)", p, delta);
else
sprintf (name2, "(%s)", p);
else
sprintf(name2, "No Symbols)");
sprintf (read_buffer, "%02ld.%-1ld%% %08lx-%08lx %s-%s",
percent / total_hits, ((percent % total_hits) * 10) / total_hits,
temp_data[i].start_addr, temp_data[i].stop_addr,
name, name2);
percent /= 100;
percent_bar = percent * (cols - 5) / total_hits;
putl (2, i * 2 + 3, cols - 4, read_buffer);
draw (2, i * 2 + 4, '-', 1, percent_bar);
}
out_hits = total_hits - in_hits;
percent = out_hits * 100;
sprintf (name, "%02ld.%-1ld%% : Other segments (%% of total in-range hits)",
percent / total_hits, ((percent % total_hits) * 10) / total_hits);
putl (2, i * 2 + 3, cols - 4, name);
percent /= 100;
percent_bar = percent * (cols - 5) / in_hits;
draw (2, i * 2 + 4, '-', 1, percent_bar);
i++;
}
out_hits = total_hits_count - total_hits;
percent = out_hits * 100;
sprintf (name, "%02ld.%-1ld%% : Outside of defined range (over total of %010ld)",
percent / total_hits_count,
((percent % total_hits_count) * 10) / total_hits_count,
total_hits_count);
putl (2, i * 2 + 3, cols - 4, name);
percent /= 100;
percent_bar = percent * (cols - 5) / total_hits_count;
draw (2, i * 2 + 4, '-', 1, percent_bar);
put_screen (debug_screen_save);
do
{ i = getykey ();
if (i == K_Control_X)
{ i = getykey ();
if (i == K_Control_W)
{ write_log (1, 1, cols - 1, rows - 1);
i = 0;
}
}
} while (i == 0);
free (debug_screen_save);
debug_screen_save = save;
put_screen (debug_screen_save);
}
/* ---------------------------------------------------------------------- */
static void
init_time (char *output, char *input, word32 addr)
{ sprintf (output, "%s", *(int *)addr ? "On " : "Off");
}
/* ---------------------------------------------------------------------- */
static int
edtime (char *text, word32 addr, int x, int y, int len, int *key)
{ if (*key == K_Return) /* Only enter toggles timer */
{ if (*(int *)addr)
reset_timer ();
else
set_timer ();
}
*key = 0;
return 1;
}
/* ---------------------------------------------------------------------- */
static int
action_init (DIALOG_ITEM dialog_data[])
{ word32 start_addr = 0, stop_addr = 0;
int ok;
if (!my_read_string ("Enter start address: "))
start_addr = parse_expression(4, read_buffer, &ok);
if (ok != ParseError_ok)
{ message (CL_Error, "Bad address: %s", read_buffer);
return (0);
}
if (!my_read_string ("Enter stop address: "))
stop_addr = parse_expression(4, read_buffer, &ok);
if (ok != ParseError_ok)
{ message (CL_Error, "Bad address: %s", read_buffer);
return (0);
}
init_eval_data (start_addr, stop_addr);
return (1);
}
/* ---------------------------------------------------------------------- */
static int
action_view (DIALOG_ITEM dialog_data[])
{ view_eval_data ();
return (1);
}
/* ---------------------------------------------------------------------- */
static void
evaluation_dialogue (void)
{ int ret = 0;
static DIALOG_ITEM dialog_data[] = {
{"Timer :", 0 , 03, 1, format_asis, eval_asis, init_time, edtime},
{"Segments :", 0 , 05, 0, format_int , eval_word, init_int , editor},
{0 , 0 , 0 , 0, 0 , 0 , 0 , 0 }
};
static BUTTON_ITEM button_data[] = {
{" ReInit ", 1, action_init},
{" View ", 1, action_view},
{" Done ", 0, action_done},
{0 , 0, 0 }
};
dialog_data[0].return_addr = (word32)&timer_is_set;
dialog_data[1].return_addr = (word32)&total_segments;
dialog ("P.A. Settings", dialog_data, button_data, &ret);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Code_Local_Menu[] = {
{"Current Highlighted Item ", 1 , "" , 0},
{"Run ~^R~", ITEM_TYPE, "\022" , 0},
{"Step into function ~S~", ITEM_TYPE, "S" , 0},
{"Step over function ~s~", ITEM_TYPE, "s" , 0},
{"Trace to current address ~^C t~", ITEM_TYPE, "\3t" , 0},
{"Animate ~^C a~", ITEM_TYPE, "\3a" , 0},
{"Toggle breakpoint ~b~", ITEM_TYPE, "b" , 0},
{"Toggle/edit breakpoint ~e~", ITEM_TYPE, "e" , 0},
{"Perfomance analyzer settings ~p~", ITEM_TYPE, "p" , 0},
{"Start performance analyzer ~^C p~", ITEM_TYPE, "\3p" , 0},
{"Display code at EIP ~i~", ITEM_TYPE, "i" , 0},
{"Set EIP to current address ~^C i~", ITEM_TYPE, "\3i" , 0},
{"Move pane's origin left one byte ~M b~", ITEM_TYPE, "\033b", 0},
{"Move pane's origin right one byte ~M f~", ITEM_TYPE, "\033f", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
code_pane_command (int key)
{ int b;
if (key == 0)
{ pop_menu (Code_Local_Menu, "Code", 1, 3, &b);
control_c = 0;
control_x = 0;
escaped = 0;
switch (b)
{ case 1:
step (2); /* Run is a global command... */
break;
case 2:
key = 'S';
break;
case 3:
key = 's';
break;
case 4:
control_c = 1;
key = 't';
break;
case 5:
control_c = 1;
key = 'a';
break;
case 6:
key = 'b';
break;
case 7:
key = 'e';
break;
case 8:
key = 'p';
break;
case 9:
control_c = 1;
key = 'p';
break;
case 10:
key = 'i';
break;
case 11:
control_c = 1;
key = 'i';
break;
case 12:
escaped = 1;
key = 'b';
break;
case 13:
escaped = 1;
key = 'f';
break;
}
}
if (control_c)
{ switch (key)
{ case 'a': /* Animate */
if (using_com_port_num)
{ message (CL_Error, "Local mode only.");
break;
}
if (!my_read_string("Time between step (tens of msecs): "))
{ unsigned long milisec;
char *endp;
int stopped = 0;
milisec = strtoul(read_buffer, &endp, 10);
if (milisec > 0)
while (!stopped)
{ step(0);
stopped = short_sleep(milisec);
}
}
break;
case 't': /* Trace */
b = set_breakpoint (BP_Code, 0, code_pane_pos[pane_pos]);
step (2);
reset_breakpoint (b);
break;
case 'i': /* Set EIP to current */
a_tss.tss_eip = code_pane_pos[pane_pos];
break;
case 'p': /* Start perfom. analyzer*/
if (timer_is_set)
{ start_evaluate ();
step (2);
stop_evaluate ();
reset_timer ();
} else
message (CL_Error, "Timer has not been set -- Action aborted.");
break;
}
}
if (control_x)
{ switch (key)
{ case '/': /* Save to register */
key = my_get_char ("Save address to which register (0..A..z)? ");
if (key >= '0' && key <= 'z')
registers[key - '0'] = code_pane_pos[pane_pos];
break;
case 'j': /* Load from register */
case 'J':
key = my_get_char ("Load address from which register (0..A..z)? ");
if (key >= '0' && key <= 'z')
if (registers[key - '0'])
code_pane_goto (registers[key - '0']);
break;
}
}
if (escaped)
{ switch (key)
{ case 'b': /* Move origin left */
case 'B':
code_dump_origin--;
break;
case 'f': /* Move origin right */
case 'F':
code_dump_origin++;
break;
case 'v': /* PageUp */
case 'V':
escaped = 0;
key = K_PageUp;
break;
}
}
if (!(control_c || control_x || escaped))
{ switch (key)
{ case K_Up:
case K_EUp:
case K_Control_B:
case K_Control_P:
if (pane_pos > 0)
pane_pos--;
else
code_pane_goto (code_skip (code_dump_origin, -1));
break;
case K_Down:
case K_EDown:
case K_Control_F:
case K_Control_N:
if (pane_pos < toplines - 2)
pane_pos++;
else
code_dump_origin =
code_pane_pos[0] == code_pane_pos[1]
? code_pane_pos[2] : code_pane_pos[1];
break;
case K_PageUp:
case K_EPageUp:
code_dump_origin = code_skip (code_dump_origin, 2 - toplines);
break;
case K_PageDown:
case K_EPageDown:
case K_Control_V:
code_dump_origin = code_dump_last + 1;
break;
case 'b':
case 'B':
b = get_breakpoint (BP_Code, -1, code_pane_pos[pane_pos]);
if (b != -1)
reset_breakpoint (b);
else
b = set_breakpoint (BP_Code, 4, code_pane_pos[pane_pos]);
break;
case 'e':
case 'E':
b = get_breakpoint (BP_Code, -1, code_pane_pos[pane_pos]);
if (b == -1)
{ b = set_breakpoint (BP_Code, 4, code_pane_pos[pane_pos]);
if (edit_breakpoint(b))
reset_breakpoint (b);
} else
edit_breakpoint (b);
break;
case 'i':
case 'I':
code_pane_goto (a_tss.tss_eip);
break;
case 'p':
case 'P':
evaluation_dialogue ();
break;
case 's':
step (1);
break;
case 'S':
step (0);
break;
default:
if ((key == '_') || (key == '%') ||
(key == '(') || (key >= '0' && key <= '9'))
{ int res, ok;
char s[2], *p;
s[0] = key; s[1] = '\0';
if (last_addr[0])
ok = !read_string (last_addr);
else
ok = !read_string (key == '=' ? "" : s);
strcpy (last_addr, read_buffer);
p = read_buffer;
while (*p != 0 && *p == ' ')
p++;
if (*p)
{ if (ok)
{ res = parse_expression (4, read_buffer, &ok);
if (ok == ParseError_ok)
{ message (CL_Info, "Found address %s.", read_buffer);
code_pane_goto (res);
last_addr[0] = 0;
}
else
message (CL_Error, "Bad address: %s", read_buffer);
}
}
}
break;
}
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Register_Local_Menu[] = {
{"Current Highlighted Item ", 1 , "" , 0},
{"Modify current register ~^C m~", ITEM_TYPE, "\3m", 0},
{"Undo last modification ~^C u~", ITEM_TYPE, "\3u", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
register_pane_command (int key)
{ int curr = pane_pos + reg_pane_origin;
int b;
if (key == 0)
{ pop_menu (Register_Local_Menu, "Registers", cols - 33, 3, &b);
switch (b)
{ case 1:
control_c = 1;
key = 'm';
break;
case 2:
control_c = 1;
key = 'u';
break;
}
}
if (control_c)
{ switch (key)
{ case 'm':
case 'M':
{ int res, ok;
if (!my_read_string ("New value: ") && read_buffer[0])
{ res = parse_expression (4, read_buffer, &ok);
if (ok == ParseError_ok)
switch (regs_type[curr])
{ case 's':
put_undo (®ister_undo, (word32)(regs_addr[curr]),
*regs_addr[curr], 2);
*(unsigned short *)(regs_addr[curr]) = res & 0xffff;
break;
case 'f':
put_undo (®ister_undo, 0,
a_tss.tss_eflags, 0);
a_tss.tss_eflags = (a_tss.tss_eflags & ~0xed5) | (res & 0xed5);
break;
default:
put_undo (®ister_undo, (word32)(regs_addr[curr]),
*regs_addr[curr], 4);
*regs_addr[curr] = res;
}
else message (CL_Error, "Bad expression: %s", read_buffer);
}
break;
}
case 'u':
case 'U':
{ word32 u_addr, u_val;
int u_size;
if (get_undo (®ister_undo, &u_addr, &u_val, &u_size))
{ switch (u_size)
{ case 2: /* 's' */
*(unsigned short *)(u_addr) = u_val & 0xffff;
break;
case 0: /* 'f' */
a_tss.tss_eflags = (a_tss.tss_eflags & ~0xed5) | (u_val & 0xed5);
break;
case 4:
*(word32 *)u_addr = u_val;
break;
}
}
break;
}
}
}
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else if (reg_pane_origin)
reg_pane_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (regs_type[pane_pos + reg_pane_origin + 1])
if (pane_pos < toplines - 2)
pane_pos++;
else
reg_pane_origin++;
break;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Flag_Local_Menu[] = {
{"Current ", 1 , "" , 0},
{"~T~oggle flag", ITEM_TYPE, "t", 0},
{"~S~et flag ", ITEM_TYPE, "s", 0},
{"~R~eset flag ", ITEM_TYPE, "r", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
flag_pane_command (int key)
{ static unsigned flagbits[] =
{ 0x0001, 0x0004, 0x0010, 0x0040, 0x0080, 0x0200, 0x0400, 0x0800 };
int b, curr = pane_pos + flag_pane_origin;
if (key == 0)
{ pop_menu (Flag_Local_Menu, "Flag", cols - 20, 3, &b);
switch (b)
{ case 1:
a_tss.tss_eflags ^= flagbits[curr];
break;
case 2:
a_tss.tss_eflags |= flagbits[curr];
break;
case 3:
a_tss.tss_eflags &= ~flagbits[curr];
break;
}
}
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else if (flag_pane_origin)
flag_pane_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (curr < 7)
if (pane_pos < toplines - 2)
pane_pos++;
else
flag_pane_origin++;
break;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Breakpoint_Local_Menu[] = {
{"Current Highlighted Item ", 1 , "" , 0},
{"Delete breakpoint ~^D~", ITEM_TYPE, "\4" , 0},
{"Edit breakpoint ~^E~", ITEM_TYPE, "\5" , 0},
{"Display Breakpoint ", ITEM_TYPE, "" , 0},
{"Clear from current breakpoint ~^K~", ITEM_TYPE, "\013", 0},
{"Restore breakpoint(s) ~^Y~", ITEM_TYPE, "\031", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
breakpoint_pane_command (int key)
{
int b = breakpoint_count ? pane_pos + breakpoint_origin : -1;
int last = breakpoint_count && (b == breakpoint_count - 1);
BP_ENTRY *del_bp;
if (key == 0)
{ pop_menu (Breakpoint_Local_Menu, "Breakpoint", cols - 40, rows - 15, &b);
control_c = 0;
control_x = 0;
escaped = 0;
switch (b)
{ case 1:
key = K_Control_D;
break;
case 2:
key = K_Control_E;
break;
case 3:
key = K_Return;
break;
case 4:
key = K_Control_K;
break;
case 5:
key = K_Control_Y;
break;
}
}
b = breakpoint_count ? pane_pos + breakpoint_origin : -1;
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Delete:
case K_EDelete:
case K_Control_D:
if (b != -1)
reset_breakpoint (b);
if (!last)
break;
/* else fall through */
case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else
if (breakpoint_origin > 0)
breakpoint_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (!last)
if (pane_pos < bottomlines / 2 - 1)
pane_pos++;
else
breakpoint_origin++;
break;
case K_Return:
if (b != -1)
if (breakpoint_table[b].type == BP_Code)
code_pane_goto (breakpoint_table[b].addr);
else
data_dump_origin = breakpoint_table[b].addr;
break;
case K_Control_E:
if (b != -1)
edit_breakpoint(b);
break;
case K_Control_K:
{ int temp = breakpoint_count - 1;
if (b >= 0)
while (temp >= b)
reset_breakpoint (temp--);
break;
}
case K_Control_Y:
{ word32 u_addr, u_val;
int u_size;
if (get_undo (&breakpoint_undo, &u_addr, &u_val, &u_size))
{ del_bp = (BP_ENTRY *)u_val;
b = set_breakpoint (del_bp->type, del_bp->length, del_bp->addr);
breakpoint_table[b].sub_type = del_bp->sub_type;
breakpoint_table[b].count = del_bp->count;
strcpy (breakpoint_table[b].condition, del_bp->condition);
free (del_bp);
}
break;
}
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static int
action_search (DIALOG_ITEM dialog_data[])
{ int size = *(int *)(dialog_data[0].return_addr);
word32 start_at = *(word32 *)(dialog_data[1].return_addr);
word32 search_for = *(word32 *)(dialog_data[2].return_addr);
word8 search_byte, *mem_byte;
word16 search_word, *mem_word;
word32 stop_at, *mem_long;
int i, buf_size, found = 0;
stop_at = start_at;
if (!size || !valid_addr (start_at, size))
return (0);
for (i = 0; i < MAX_AREA && !found; i++)
if (start_at + size <= areas[i].last_addr &&
start_at >= areas[i].first_addr)
{ stop_at = areas[i].last_addr;
found = 1;
}
if (!found && start_at + size <= dos_mem_hi && start_at >= dos_mem_lo)
{ stop_at = dos_mem_hi;
found = 1;
}
if (!found)
return (0);
found = 0;
switch (size)
{ case 1:
search_byte = (word8)(search_for & 0xff);
do
{ if (stop_at < start_at + size)
break;
buf_size = stop_at - start_at;
if (buf_size > 4096)
buf_size = 4096;
read_child (start_at, read_buffer, buf_size);
mem_byte = (word8 *)read_buffer;
for (i = 0; i < buf_size; i++)
if (mem_byte[i] == search_byte)
{ found = 1;
start_at += i;
break;
}
if (!found)
start_at += 4096;
} while (!found);
break;
case 2:
search_word = (word16)(search_for & 0xffff);
do
{ if (stop_at < start_at + size)
break;
buf_size = stop_at - start_at;
if (buf_size > 4096)
buf_size = 4096;
read_child (start_at, read_buffer, buf_size);
buf_size /= 2;
mem_word = (word16 *)read_buffer;
for (i = 0; i < buf_size; i++)
if (mem_word[i] == search_word)
{ found = 1;
start_at += i * 2;
break;
}
if (!found)
start_at += 4096;
} while (!found);
break;
default:
size = 4;
do
{ if (stop_at < start_at + size)
break;
buf_size = stop_at - start_at;
if (buf_size > 4096)
buf_size = 4096;
read_child (start_at, read_buffer, buf_size);
buf_size /= 4;
mem_long = (word32 *)read_buffer;
for (i = 0; i < buf_size; i++)
if (mem_long[i] == search_for)
{ found = 1;
start_at += i * 4;
break;
}
if (!found)
start_at += 4096;
} while (!found);
break;
}
if (!found)
return (0);
*(word32 *)(dialog_data[1].return_addr) = start_at + size;
*(word32 *)(dialog_data[0].return_addr) = size;
data_dump_origin = start_at;
pane_pos = 0;
redraw (0);
return (1);
}
/* ---------------------------------------------------------------------- */
static void
search_memory (void)
{ int size = 1, ret = 2;
word32 start_at = areas[A_data].first_addr, search_for = 0;
static DIALOG_ITEM dialog_data[] = {
{"Size :", 0 , 03, 1, format_int , eval_word, init_int , editor},
{"Start at :", 0 , 50, 1, format_addr, eval_word, init_addr, editor},
{"Search for :", 0 , 10, 1, format_word, eval_word, init_word, editor},
{0 , 0 , 0 , 0, 0 , 0 , 0 , 0 }
};
static BUTTON_ITEM button_data[] = {
{" Search ", 1, action_search},
{" Done ", 0, action_done },
{0 , 0, 0 }
};
dialog_data[0].return_addr = (word32)&size;
dialog_data[1].return_addr = (word32)&start_at;
dialog_data[2].return_addr = (word32)&search_for;
dialog ("Memory Search", dialog_data, button_data, &ret);
}
/* ---------------------------------------------------------------------- */
static void
port_io_add_action (DIALOG_ITEM d[], int action,
word32 port, word32 size, word32 data)
{ unsigned char action_id, *p, fmt[ACTION_HIST_SIZE];
memcpy ((char *)(d[1].return_addr), (char *)(d[2].return_addr), ACTION_HIST_SIZE);
memcpy ((char *)(d[2].return_addr), (char *)(d[3].return_addr), ACTION_HIST_SIZE);
memcpy ((char *)(d[3].return_addr), (char *)(d[4].return_addr), ACTION_HIST_SIZE);
memcpy ((char *)(d[4].return_addr), (char *)(d[5].return_addr), ACTION_HIST_SIZE);
p = (char *)(d[5].return_addr);
action_id = p[strlen (p) + 1];
action_id++;
sprintf (fmt, "%%03d %%s 0x%%04lx%%-%lds0x%%0%ldlx", 9 - size * 2, size * 2);
sprintf (p, fmt, action_id, action ? "Out" : " In", port, " ", data);
p[strlen (p) + 1] = action_id;
}
/* ---------------------------------------------------------------------- */
static int
action_outp (DIALOG_ITEM dialog_data[])
{ int size = *(int *)(dialog_data[6].return_addr);
word32 port = *(word32 *)(dialog_data[7].return_addr);
word32 data = *(word32 *)(dialog_data[8].return_addr);
port &= 0xffff;
if (!port || !size)
return (0);
switch (size)
{ case 2:
data &= 0xffff;
outportw (port, data);
break;
case 4:
outportl (port, data);
break;
default:
data &= 0xff;
outportb (port, data);
break;
}
port_io_add_action (dialog_data, 1, port, size, data);
return (1);
}
/* ---------------------------------------------------------------------- */
static int
action_inp (DIALOG_ITEM dialog_data[])
{ int size = *(int *)(dialog_data[6].return_addr);
word32 port = *(word32 *)(dialog_data[7].return_addr);
word32 data;
port &= 0xffff;
if (!port || !size)
return (0);
switch (size)
{ case 2:
data = inportw (port) & 0xffff;
break;
case 4:
data = inportl (port);
break;
default:
*(int *)(dialog_data[6].return_addr) = 1;
size = 1;
data = inportb (port) & 0xff;
break;
}
*(word32 *)(dialog_data[8].return_addr) = data;
port_io_add_action (dialog_data, 0, port, size, data);
return (1);
}
/* ---------------------------------------------------------------------- */
static void
read_write_port (void)
{ int ret = 11;
static int size = 1;
static word32 port = 0x20, data = 0;
static char last_act_0[ACTION_HIST_SIZE] = " ID Action Port Value";
static char last_act_1[ACTION_HIST_SIZE] = "--- --- ------ ----------\0";
static char last_act_2[ACTION_HIST_SIZE] = "--- --- ------ ----------\0";
static char last_act_3[ACTION_HIST_SIZE] = "--- --- ------ ----------\0";
static char last_act_4[ACTION_HIST_SIZE] = "--- --- ------ ----------\0";
static char last_act_5[ACTION_HIST_SIZE] = "--- --- ------ ----------\0\377";
static DIALOG_ITEM dialog_data[] = {
{"History:", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{" ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{" ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{" ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{" ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{" ", 0, 60, 0, format_asis, eval_asis, init_asis, editor},
{"Size :", 0, 03, 1, format_int , eval_word, init_int , editor},
{"Port :", 0, 10, 1, format_word, eval_word, init_word, editor},
{"Data :", 0, 10, 1, format_word, eval_word, init_word, editor},
{0 , 0, 0 , 0, 0 , 0 , 0 , 0 }
};
static BUTTON_ITEM button_data[] = {
{" Out ", 1, action_outp},
{" In ", 1, action_inp },
{" Done ", 0, action_done},
{0 , 0, 0 }
};
dialog_data[0].return_addr = (word32)last_act_0;
dialog_data[1].return_addr = (word32)last_act_1;
dialog_data[2].return_addr = (word32)last_act_2;
dialog_data[3].return_addr = (word32)last_act_3;
dialog_data[4].return_addr = (word32)last_act_4;
dialog_data[5].return_addr = (word32)last_act_5;
dialog_data[6].return_addr = (word32)&size;
dialog_data[7].return_addr = (word32)&port;
dialog_data[8].return_addr = (word32)&data;
dialog ("Port IO", dialog_data, button_data, &ret);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Data_Local_Menu[] = {
{"Current Highlighted Item ", 1 , "" , 0},
{"Toggle data write breakpoint ~w~", ITEM_TYPE, "w" , 0},
{"Toggle read/write breakpoint ~r~", ITEM_TYPE, "r" , 0},
{"Display data at EIP ~i~", ITEM_TYPE, "i" , 0},
{"Display data at ESP ~s~", ITEM_TYPE, "s" , 0},
{"Display data at current pointer ~*~", ITEM_TYPE, "*" , 0},
{"Display data at last address(es) ~@~", ITEM_TYPE, "@" , 0},
{"Move pane's origin left ~M b~", ITEM_TYPE, "\033b", 0},
{"Move pane's origin right ~M f~", ITEM_TYPE, "\033f", 0},
{"Display as bytes ~b~", ITEM_TYPE, "b" , 0},
{"Display as words ~h~", ITEM_TYPE, "h" , 0},
{"Display as dwords ~f~", ITEM_TYPE, "f" , 0},
{"Port access ~p~", ITEM_TYPE, "p" , 0},
{"Modify data at cursor ~^C m~", ITEM_TYPE, "\3m" , 0},
{"Undo modification(s) ~^C u~", ITEM_TYPE, "\3u" , 0},
{"Search memory ~^C s~", ITEM_TYPE, "\3s" , 0},
{"Data structure supports ~n~", ITEM_TYPE, "n" , 0},
{0 , 0 , "" , 0}
};
static word32 old_dump_address[5] = {0, 0, 0, 0, 0};
/* ---------------------------------------------------------------------- */
static void
data_pane_command (int key)
{ word32 v = data_dump_origin + pane_pos;
int res, ok, bad = 0;
char *p, *p0, q, s[2];
if (key == 0)
{ pop_menu (Data_Local_Menu, "Data", 1, rows - 19, &res);
control_c = 0;
control_x = 0;
escaped = 0;
switch (res)
{ case 1:
key = 'w';
break;
case 2:
key = 'r';
break;
case 3:
key = 'i';
break;
case 4:
key = 's';
break;
case 5:
key = '*';
break;
case 6:
key = '@';
break;
case 7:
escaped = 1;
key = 'b';
break;
case 8:
escaped = 1;
key = 'f';
break;
case 9:
key = 'b';
break;
case 10:
key = 'h';
break;
case 11:
key = 'f';
break;
case 12:
key = 'p';
break;
case 13:
control_c = 1;
key = 'm';
break;
case 14:
control_c = 1;
key = 'u';
break;
case 15:
control_c = 1;
key = 's';
case 16:
key = 'n';
break;
}
}
if (control_x)
{ switch (key)
{ case '/': /* Save to register */
key = my_get_char ("Save address to which register (0..A..z)? ");
if (key >= '0' && key <= 'z')
registers[key - '0'] = v;
break;
case 'j': /* Load from register */
case 'J':
key = my_get_char ("Load address from which register (0..A..z)? ");
if (key >= '0' && key <= 'z')
if (registers[key - '0'])
{ data_dump_origin = registers[key - '0'];
pane_pos = 0;
}
break;
}
}
if (control_c)
{ switch (key)
{ case 'm':
case 'M':
{ if (!my_read_string ("New value: "))
{ p = read_buffer;
do
{ while (*p == ' ') p++;
switch (*p)
{ case '\0':
break;
case '\'':
case '"':
if (data_dump_size != 1)
{ *p = 0;
message (CL_Error, "Strings must be entered in byte mode");
break;
}
q = *p++;
p0 = p;
while (*p != q && *p)
p++;
if (*p)
{ while (p0 != p)
{ if (valid_addr (v, 1))
write_child (v, p0, 1);
else
bad = 1;
p0++, v++;
}
if (q == '"')
{ if (valid_addr (v, 1))
{ q = 0;
write_child (v, &q, 1);
q = '"';
}
else
bad = 1;
v++;
}
p++;
}
else
message (CL_Error, "String constant not terminated");
break;
default:
p0 = p;
while (*p != ',' && *p)
p++;
q = *p;
*p = 0;
res = parse_expression (4, p0, &ok);
if (ok == ParseError_ok)
{ *p = q;
if (valid_addr (v, data_dump_size))
{ word32 u_val;
read_child (v, &u_val, data_dump_size);
put_undo (&data_undo, v, u_val, data_dump_size);
write_child (v, &res, data_dump_size);
} else
bad = 1;
v += data_dump_size;
} else
{ message (CL_Error, "Invalid expression: %s", p0);
bad = 1;
}
}
if (*p == ',')
p++;
} while (*p);
if (bad)
message (CL_Error, "Part of the data could not be written");
else
message (CL_Info, "Memory modified.");
}
break;
}
case 'u':
case 'U':
{ word32 u_addr, u_val, old_val = 0;
int u_size;
if (get_undo (&data_undo, &u_addr, &u_val, &u_size))
{ read_child (u_addr, &old_val, u_size);
write_child (u_addr, &u_val, u_size);
message (CL_Msg,
"%d byte(s) at %08lx has been undone from %08lx to %08lx",
u_size, u_addr, old_val, u_val);
}
break;
}
case 's':
case 'S':
search_memory ();
break;
}
}
if (escaped)
{ switch (key)
{ case 'b':
case 'B':
data_dump_origin--;
break;
case 'f':
case 'F':
data_dump_origin++;
break;
case 'v':
case 'V':
escaped = 0;
key = K_PageUp;
break;
}
}
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Up:
case K_EUp:
case K_Control_P:
if (pane_pos >= 8)
pane_pos -= 8;
else
data_dump_origin -= 8;
break;
case K_Down:
case K_EDown:
case K_Control_N:
if (v + 8 <= data_dump_last)
pane_pos += 8;
else
data_dump_origin += 8;
break;
case K_Left:
case K_ELeft:
case K_Control_B:
if (pane_pos > 0)
pane_pos -= data_dump_size;
else
data_dump_origin -= 8, pane_pos = 8 - data_dump_size;
break;
case K_Right:
case K_ERight:
case K_Control_F:
if (v + data_dump_size <= data_dump_last)
pane_pos += data_dump_size;
else
data_dump_origin += 8, pane_pos -= (8 - data_dump_size);
break;
case K_PageUp:
case K_EPageUp:
data_dump_origin -= (data_dump_last + 1 - data_dump_origin);
break;
case K_PageDown:
case K_EPageDown:
case K_Control_V:
data_dump_origin = data_dump_last + 1;
break;
case 's':
case 'S':
data_dump_origin = a_tss.tss_esp;
pane_pos = 0;
break;
case 'i':
case 'I':
data_dump_origin = a_tss.tss_eip;
data_dump_size = 1;
pane_pos = 0;
break;
case '*':
if (valid_addr (v, 4))
{ for (res = 1; res < 5; res++)
old_dump_address[res - 1] = old_dump_address[res];
old_dump_address[4] = data_dump_origin + pane_pos;
read_child (v, &data_dump_origin, 4);
pane_pos = 0;
} else
message (CL_Error, "Pointer points to an invalid address.");
break;
case '@':
if (!old_dump_address[4])
old_dump_address[4] = data_dump_origin;
data_dump_origin = old_dump_address[4];
pane_pos = 0;
for (res = 4; res > 0; res--)
old_dump_address[res] = old_dump_address[res - 1];
old_dump_address[0] = data_dump_origin;
break;
case 'b':
case 'B':
data_dump_size = 1;
break;
case 'h':
case 'H':
data_dump_size = 2;
break;
case 'f':
case 'F':
data_dump_size = 4;
break;
case 'n':
case 'N':
if (!running_xsupport)
{ running_xsupport = 1;
if (extern_data_support(v))
running_xsupport = 0;
break;
}
case 'p':
case 'P':
read_write_port();
break;
case 'w':
case 'W':
res = get_breakpoint (BP_Write, data_dump_size, v);
if (res == -1)
set_breakpoint (BP_Write, data_dump_size, v);
else
reset_breakpoint (res);
break;
case 'r':
case 'R':
res = get_breakpoint (BP_Read, data_dump_size, v);
if (res == -1)
set_breakpoint (BP_Read, data_dump_size, v);
else
reset_breakpoint (res);
break;
case 'e':
case 'E':
res = get_breakpoint (BP_Read, -1, v);
if (res == -1)
{ res = set_breakpoint (BP_Read, data_dump_size, v);
if (edit_breakpoint(res))
reset_breakpoint (res);
} else
edit_breakpoint (res);
break;
default:
if ((key == '_') || (key == '%') ||
(key == '(') || (key >= '0' && key <= '9'))
{ s[0] = key; s[1] = '\0';
if (last_addr[0])
ok = !read_string (last_addr);
else
ok = !read_string (key == '=' ? "" : s);
strcpy (last_addr, read_buffer);
if (ok)
{ p = read_buffer;
while (*p != 0 && *p == ' ')
p++;
if (*p)
{ res = parse_expression (4, p, &ok);
if (ok == ParseError_ok)
{ data_dump_origin = res;
pane_pos = 0;
for (res = 1; res < 5; res++)
old_dump_address[res - 1] = old_dump_address[res];
old_dump_address[4] = data_dump_origin;
last_addr[0] = 0;
message (CL_Info, "Found address %s.", p);
}
else
message (CL_Error, "Bad address: %s", p);
}
}
}
break;
}
pane_pos &= ~(data_dump_size - 1);
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Npx_Local_Menu[] = {
{"Current Item ", 1 , "" , 0},
{"Empty register ~^C e~", ITEM_TYPE, "\3e", 0},
{"Zero register ~^C z~", ITEM_TYPE, "\3z", 0},
{"Negate register ~^C n~", ITEM_TYPE, "\3n", 0},
{"Modify register ~^C m~", ITEM_TYPE, "\3m", 0},
{"Undo modification ~^C u~", ITEM_TYPE, "\3u", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
npx_pane_command (int key)
{ NPX *del_npx;
int reg = pane_pos - 3, rotreg = 0, tag = 0;
int regp = (reg >= 0);
int b;
save_npx ();
if (regp)
{ rotreg = (reg + (npx.status >> 11)) & 7;
tag = (npx.tag >> (rotreg * 2)) & 3;
}
if (key == 0)
{ pop_menu (Npx_Local_Menu, "Npx", 1, 3, &b);
control_c = 1;
control_x = 0;
escaped = 0;
switch (b)
{ case 1:
key = 'e';
break;
case 2:
key = 'z';
break;
case 3:
key = 'n';
break;
case 4:
key = 'm';
break;
case 5:
key = 'u';
break;
}
}
if (control_c)
{ switch (key)
{ case 'e':
case 'E':
if (regp)
{ tag = 3;
del_npx = malloc (sizeof (NPX));
memcpy (del_npx, &npx, sizeof (NPX));
put_undo (&npx_undo, 1, (word32)del_npx, 1);
memset (&npx.reg[reg], 0, sizeof (NPXREG));
}
break;
case 'z':
case 'Z':
if (regp)
{ tag = 1;
del_npx = malloc (sizeof (NPX));
memcpy (del_npx, &npx, sizeof (NPX));
put_undo (&npx_undo, 1, (word32)del_npx, 1);
memset (&npx.reg[reg], 0, sizeof (NPXREG));
}
break;
case 'n':
case 'N':
if (regp)
{ del_npx = malloc (sizeof (NPX));
memcpy (del_npx, &npx, sizeof (NPX));
put_undo (&npx_undo, 1, (word32)del_npx, 1);
npx.reg[reg].sign = !npx.reg[reg].sign;
}
break;
case 'm':
case 'M':
{ char *p, *endp;
double d;
if (!my_read_string ("New value: "))
{ p = read_buffer;
del_npx = malloc (sizeof (NPX));
memcpy (del_npx, &npx, sizeof (NPX));
put_undo (&npx_undo, 1, (word32)del_npx, 1);
while (*p == ' ')
p++;
if (*p == '\0')
break;
strlwr (p);
if (strcmp (p, "+inf") == 0
|| strcmp (p, "inf") == 0
|| strcmp (p, "-inf") == 0)
{ tag = 2;
npx.reg[reg].exponent = 0x7fff;
npx.reg[reg].sig3 = 0x8000;
npx.reg[reg].sig2
= npx.reg[reg].sig1
= npx.reg[reg].sig0 = 0;
npx.reg[reg].sign = (*p == '-');
} else
{ d = strtod (p, &endp);
if (*p != '\0' && *endp)
message (CL_Error, "Expression not understood");
else
{ tag = (d == 0.0);
*((long double *)(npx.reg + reg)) = (long double) d;
npx.reg[reg].sign = (*p == '-'); /* for -Zero */
}
}
}
break;
}
case 'u':
case 'U':
{ word32 u_addr, u_val;
int u_size;
if (get_undo (&npx_undo, &u_addr, &u_val, &u_size))
{ del_npx = (NPX *)u_val;
memcpy (&npx, del_npx, sizeof (NPX));
}
break;
}
}
}
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0) pane_pos--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if ((pane_pos < 10) && (pane_pos < toplines - 2)) pane_pos++;
break;
}
if (regp)
npx.tag = (npx.tag & ~(3 << (rotreg * 2))) | (tag << (rotreg * 2));
load_npx ();
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Stack_Local_Menu[] = {
{"Current Highlighted", 1 , "" , 0},
{"Goto function ~^M~", ITEM_TYPE, "\015", 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
stack_pane_command (int key)
{
int b;
if (key == 0)
{ pop_menu (Stack_Local_Menu, "Stack", 1, 3, &b);
control_c = 0;
control_x = 0;
escaped = 0;
switch (b)
{ case 1:
key = K_Return;
break;
}
}
if (!(escaped || control_c || control_x))
switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else
if (stack_dump_origin)
stack_dump_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (pane_pos < stack_dump_last)
pane_pos++;
else
if (stack_dump_more)
stack_dump_origin++;
break;
case K_Return:
code_pane_goto (stack_dump_pos[pane_pos]);
stack_pane_active = 0;
code_pane_active = 1;
pane = 0;
break;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Info_Local_Menu[] = {
{"Current Highlighted Item", 1 , "", 0},
{"No command available ", ITEM_TYPE, "", 0},
{0 , 0 , "", 0}
};
/* ---------------------------------------------------------------------- */
static void
info_pane_command (int key)
{ int b;
/* No keys recognized. */
if (key == 0)
{ pop_menu (Info_Local_Menu, "Info", 1, 3, &b);
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static void
fullscr_listwild_handler (word32 sym_num)
{ whereis_pane_sym = realloc (whereis_pane_sym,
(++whereis_sym_count) * sizeof (word32));
whereis_pane_sym[whereis_sym_count - 1] = sym_num;
}
/* ---------------------------------------------------------------------- */
static void
init_whereis_sym (void)
{ char *p;
if (!my_read_string ("Search for: ") && read_buffer[0] != '\0')
{ whereis_pane_sym = realloc (whereis_pane_sym, 0);
p = read_buffer;
while (*p == ' ') p++;
syms_listwild (p, &fullscr_listwild_handler);
pane_pos = whereis_origin = 0;
if (whereis_sym_count >= 10)
message (CL_Info, "There were %d symbols that matched",
whereis_sym_count);
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM WhereIs_Local_Menu[] = {
{"Current Highlighted Item ", 1 , "" , 0},
{"Goto beginning of list ~M <~", ITEM_TYPE, "\033<", 0},
{"Goto end of list ~M >~", ITEM_TYPE, "\033>", 0},
{"Search for symbol(s) ", ITEM_TYPE, "" , 0},
{0 , 0 , "" , 0}
};
/* ---------------------------------------------------------------------- */
static void
whereis_pane_command (int key)
{
int no = whereis_origin + pane_pos;
int b;
if (key == 0)
{ pop_menu (WhereIs_Local_Menu, "WhereIs", 1, 3, &b);
control_c = 0;
control_x = 0;
escaped = 0;
switch (b)
{ case 1:
key = K_Home;
break;
case 2:
key = K_End;
break;
case 3:
key = '_';
break;
}
}
if (escaped)
{ switch (key)
{ case 'v':
case 'V':
escaped = 0;
key = K_PageUp;
break;
case '>':
escaped = 0;
key = K_End;
break;
case '<':
escaped = 0;
key = K_Home;
break;
}
}
if (!(escaped || control_c || control_x))
{ switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else
if (whereis_origin)
whereis_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (no < whereis_sym_count - 1)
if (pane_pos < toplines - 2)
pane_pos++;
else
whereis_origin++;
break;
case K_Home:
case K_EHome:
pane_pos = whereis_origin = 0;
break;
case K_End:
case K_EEnd:
if (whereis_sym_count > toplines - 1)
{ whereis_origin = whereis_sym_count - toplines;
pane_pos = toplines - 2;
}
else
{ whereis_origin = 0;
pane_pos = whereis_sym_count ? whereis_sym_count - 1 : 0;
}
break;
case K_PageDown:
case K_EPageDown:
case K_Control_V:
if (whereis_origin + toplines < whereis_sym_count)
{ whereis_origin += toplines - 1;
if (whereis_origin + pane_pos >= whereis_sym_count)
pane_pos = whereis_sym_count - 1 - whereis_origin;
}
break;
case K_PageUp:
case K_EPageUp:
if (whereis_origin > toplines)
whereis_origin -= toplines;
else
whereis_origin = pane_pos = 0;
break;
case K_Return:
if (whereis_sym_count)
{ char typ;
unsigned long ul;
syms_get (whereis_pane_sym[no], &ul, &typ);
switch (toupper (typ))
{ case 'T':
code_pane_goto (ul);
whereis_pane_active = 0;
code_pane_active = 1;
pane = 0;
break;
case 'B':
case 'D':
data_dump_origin = ul;
pane_positions[4] = 0;
break;
}
}
break;
default:
if ((key == '_') || (key >= '0' && key <= '9'))
{ char s[2], *p;
s[0] = key; s[1] = '\0';
if (!read_string (key == '=' ? "" : s) && read_buffer[0] != '\0')
{ whereis_pane_sym = realloc (whereis_pane_sym, 0);
whereis_sym_count = 0;
p = read_buffer;
while (*p == ' ') p++;
syms_listwild (p, &fullscr_listwild_handler);
pane_pos = whereis_origin = 0;
if (whereis_sym_count >= 10)
message (CL_Info, "There were %d symbols that matched",
whereis_sym_count);
}
}
}
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Module_Local_Menu[] = {
{"Current Highlighted Item", 1 , "", 0},
{"No command available ", ITEM_TYPE, "", 0},
{0 , 0 , "", 0}
};
/* ---------------------------------------------------------------------- */
static void
module_pane_command(int key)
{
int no = module_origin + pane_pos;
int b;
if (key == 0)
{ pop_menu (Module_Local_Menu, "Module", 1, 3, &b);
}
if (escaped)
{ switch (key)
{ case 'v':
case 'V':
escaped = 0;
key = K_PageUp;
break;
case '>':
escaped = 0;
key = K_End;
break;
case '<':
escaped = 0;
key = K_Home;
break;
}
}
if (!(escaped || control_c || control_x))
{ switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
if (pane_pos > 0)
pane_pos--;
else
if (module_origin)
module_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
if (no < module_text_count - 1)
if (pane_pos < toplines - 2)
pane_pos++;
else
module_origin++;
break;
case K_Home:
case K_EHome:
pane_pos = module_origin = 0;
break;
case K_End:
case K_EEnd:
if (module_text_count > toplines - 1)
{ module_origin = module_text_count - toplines;
pane_pos = toplines - 2;
}
else
{ module_origin = 0;
pane_pos = module_text_count ? module_text_count - 1 : 0;
}
break;
case K_PageDown:
case K_EPageDown:
case K_Control_V:
if (module_origin + toplines <= module_text_count)
{ module_origin += toplines - 1;
if (module_origin + pane_pos >= module_text_count)
pane_pos = module_text_count - 1 - module_origin;
}
break;
case K_PageUp:
case K_EPageUp:
if (module_origin > toplines - 1)
module_origin -= toplines - 1;
else
module_origin = pane_pos = 0;
break;
case K_Return:
if (no)
if (!my_read_string ("Line number: "))
{ unsigned long ul;
char *endp;
ul = strtoul (read_buffer, &endp, 0);
ul = get_linenum (no - 1, ul);
code_pane_goto (ul);
module_pane_active = 0;
code_pane_active = 1;
pane = 0;
}
break;
case K_Control_G:
module_pane_active = 0;
code_pane_active = 1;
pane = 0;
break;
}
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static MENU_ITEM Help_Local_Menu[] = {
{"Current Highlighted Item", 1 , "", 0},
{"No command available ", ITEM_TYPE, "", 0},
{0 , 0 , "", 0}
};
/* ---------------------------------------------------------------------- */
static void
help_pane_command(int key)
{
int no = help_origin + pane_pos;
int b;
if (key == 0)
{ pop_menu (Help_Local_Menu, "Help", 1, 3, &b);
}
if (escaped)
{ switch (key)
{ case 'v':
case 'V':
escaped = 0;
key = K_PageUp;
break;
case '>':
escaped = 0;
key = K_End;
break;
case '<':
escaped = 0;
key = K_Home;
break;
}
}
if (!(escaped || control_c || control_x))
{ switch (key)
{ case K_Left:
case K_ELeft:
case K_Up:
case K_EUp:
case K_Control_P:
case K_Control_B:
if (pane_pos > 0)
pane_pos--;
else
if (help_origin)
help_origin--;
break;
case K_Right:
case K_ERight:
case K_Down:
case K_EDown:
case K_Control_N:
case K_Control_F:
if (no < help_text_count - 1)
if (pane_pos < toplines - 2)
pane_pos++;
else
help_origin++;
break;
case K_Home:
case K_EHome:
pane_pos = help_origin = 0;
break;
case K_End:
case K_EEnd:
if (help_text_count > toplines - 1)
{ help_origin = help_text_count - toplines;
pane_pos = toplines - 2;
}
else
{ help_origin = 0;
pane_pos = help_text_count ? help_text_count - 1 : 0;
}
break;
case K_PageDown:
case K_EPageDown:
case K_Control_V:
if (help_origin + toplines <= help_text_count)
{ help_origin += toplines;
if (help_origin + pane_pos >= help_text_count)
pane_pos = help_text_count - 1 - help_origin;
}
break;
case K_PageUp:
case K_EPageUp:
if (help_origin > toplines - 1)
help_origin -= toplines - 1;
else
help_origin = pane_pos = 0;
break;
case K_Return:
case K_Control_G:
case K_Space:
help_pane_active = 0;
code_pane_active = 1;
pane = 0;
break;
}
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static void
view_regs (void)
{ WIN_TEXT read_text;
char *p;
int i;
init_text (&read_text, "Address Registers");
p = malloc (max_cols + 5);
for (i = 0; i < MAX_REGISTERS; i++)
{ sprintf (p, "Register[%c] == %08lx", i + '0', registers[i]);
add_text (&read_text, p);
}
free (p);
text_win (read_text, 40, 20);
free_text (&read_text);
}
/* ---------------------------------------------------------------------- */
static void
resize_screen(void)
{ int key, i;
while (1)
{ redraw(-1);
key = getykey();
if (key == K_Escape)
{ key = getykey ();
if (key == K_Escape)
key = K_Control_G;
}
switch (key)
{ case K_Up:
case K_EUp:
case K_Control_P:
if (toplines > 3)
{ toplines--;
bottomlines++;
}
break;
case K_Down:
case K_EDown:
case K_Control_N:
if (toplines < rows - 4)
{ toplines++;
bottomlines--;
}
break;
case K_Left:
case K_ELeft:
case K_Control_B:
switch (pane)
{ case 1: /* Top middle */
case 2: /* Top right */
if ((main_x2 > 3) && (main_x2 - main_x1 > 3))
main_x2--;
break;
case 3: /* Bottom right */
case 4: /* Bottom left */
if (main_x3 > 11 + 2 * data_dump_size)
main_x3--;
break;
default: /* Top left */
if (main_x1 > 3)
main_x1--;
break;
}
break;
case K_Right:
case K_ERight:
case K_Control_F:
switch (pane)
{ case 1: /* Top middle */
case 2: /* Top right */
if (main_x2 < cols - 4)
main_x2++;
break;
case 3: /* Bottom right */
case 4: /* Bottom left */
if (main_x3 < cols - 4)
main_x3++;
break;
default: /* Top left */
if ((main_x1 < cols - 4) && (main_x2 - main_x1 > 3))
main_x1++;
break;
}
break;
}
if (key == K_Return)
break;
if (key == K_Control_G)
break;
}
for (i = 0; i < PANECOUNT; i++)
switch(i)
{ case 3: /* Bottom panes */
case 4:
if (pane_positions[i] > bottomlines - 1)
pane_positions[i] = bottomlines - 1;
break;
default: /* Top panes */
if (pane_positions[i] > toplines - 1)
pane_positions[i] = toplines - 1;
break;
}
switch(pane)
{ case 3: /* Bottom panes */
case 4:
if (pane_pos > bottomlines - 1)
pane_pos = bottomlines - 1;
break;
default: /* Top panes */
if (pane_pos > toplines - 1)
pane_pos = toplines - 1;
break;
}
redraw(0);
}
/* ---------------------------------------------------------------------- */
static void
setup_io(void)
{
if (!my_read_string("Redirect IO to device: "))
{
if (strncmp (read_buffer, "con", 3) == 0)
using_com_port_num = 0;
if (strncmp (read_buffer, "com_one", 7) == 0)
using_com_port_num = 1;
if (strncmp (read_buffer, "com_two", 7) == 0)
using_com_port_num = 2;
if (strncmp (read_buffer, "com_three", 9) == 0)
using_com_port_num = 3;
if (strncmp (read_buffer, "com_four", 8) == 0)
using_com_port_num = 4;
if (using_com_port_num)
{ re_init_io (using_com_port_num, rows, cols);
toplines = (rows / 2) + 4;
bottomlines = rows - 3 - toplines;
main_x1 = cols - 18;
main_x2 = cols - 5;
main_x3 = 46;
}
free (code_pane_pos);
free (stack_dump_pos);
code_pane_pos = malloc ((rows + 2) * sizeof (word32));
stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
free (debug_screen_save);
free (user_screen_save);
debug_screen_save = get_screen ();
debug_screen_save[1] = debug_screen_save[2] = 0;
user_screen_save = get_screen ();
user_screen_save[1] = debug_screen_save[2] = 0;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static void
setup_screen(void)
{
int new_cols, new_rows;
if (!my_read_string("Columns: "))
{
char *endp;
new_cols = strtoul(read_buffer, &endp, 10);
if (new_cols == 0)
new_cols = cols;
}
else
new_cols = cols;
if (new_cols < 20)
new_cols = 20;
if (new_cols > max_cols)
new_cols = max_cols;
if (!my_read_string("Rows: "))
{
char *endp;
new_rows = strtoul(read_buffer, &endp, 10);
if (new_rows == 0)
new_rows = rows;
}
else
new_rows = rows;
if (new_rows < 15)
new_rows = 15;
if (new_rows > max_rows)
new_rows = max_rows;
re_init_io (using_com_port_num, new_rows, new_cols);
toplines = (rows / 2) + 4;
bottomlines = rows - 3 - toplines;
main_x1 = cols - 18;
main_x2 = cols - 5;
main_x3 = 46;
if (main_x3 > cols)
main_x3 = cols - 10;
free (code_pane_pos);
free (stack_dump_pos);
code_pane_pos = malloc ((rows + 2) * sizeof (word32));
stack_dump_pos = malloc ((rows + 2) * sizeof (word32));
free (debug_screen_save);
debug_screen_save = get_screen ();
debug_screen_save[1] = debug_screen_save[2] = 0; /* Patch cursor pos. */
redraw (0);
}
/* ---------------------------------------------------------------------- */
static void
make_pane_name (void)
{ switch (pane)
{ case CODE_PANE_NUM:
sprintf (active_pane_name, "Code Pane");
break;
case NPX_PANE_NUM:
sprintf (active_pane_name, "NPX Pane");
break;
case STACK_PANE_NUM:
sprintf (active_pane_name, "Stack Pane");
break;
case INFO_PANE_NUM:
sprintf (active_pane_name, "Info Pane");
break;
case WHEREIS_PANE_NUM:
sprintf (active_pane_name, "WhereIs Pane");
break;
case MODULE_PANE_NUM:
sprintf (active_pane_name, "Module Pane");
break;
case HELP_PANE_NUM:
sprintf (active_pane_name, "Help Pane");
break;
}
}
/* ---------------------------------------------------------------------- */
static int
make_pane_from_key (int key)
{ switch (key)
{ case 'B':
case 'b':
return (203);
break;
case 'C':
case 'c':
return (204);
break;
case 'D':
case 'd':
return (205);
break;
case 'F':
case 'f':
return (206);
break;
case 'H':
case 'h':
return (207);
break;
case 'I':
case 'i':
return (208);
break;
case 'M':
case 'm':
return (209);
break;
case 'N':
case 'n':
return (210);
break;
case 'R':
case 'r':
return (211);
break;
case 'S':
case 's':
return (212);
break;
case 'W':
case 'w':
return (213);
break;
default:
return (999);
break;
}
}
/* ---------------------------------------------------------------------- */
static void
log_current_pane (void)
{ switch (pane) /* focused pane */
{ case 1: /* Top middle */
write_log (main_x1 + 1, 2, main_x2, toplines + 1);
break;
case 2: /* Top right */
write_log (main_x2 + 1, 2, cols - 1, toplines + 1);
break;
case 3: /* Bottom right */
write_log (main_x3+1, toplines+2, cols-1, rows-1);
break;
case 4: /* Bottom left */
write_log (1, toplines + 2, main_x3, rows - 1);
break;
default: /* Top Left */
write_log (1, 2, main_x1, toplines + 1);
break;
}
}
/* ---------------------------------------------------------------------- */
static void
current_pane_taller (void)
{ switch (pane)
{ case 3: /* Breakpoint */
case 4: /* Data */
if (toplines > 3)
{ toplines--;
bottomlines++;
}
break;
default:
if (bottomlines > 1)
{ toplines++;
bottomlines--;
}
break;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static void
current_pane_wider (void)
{ switch (pane)
{ case 1: /* Register */
if (main_x1 > 3)
main_x1--;
break;
case 2: /* Flag */
break; /* No need to enlarge flag pane */
case 3: /* Breakpoint */
if (main_x3 > 11 + 2 * data_dump_size)
main_x3--;
break;
case 4: /* Data */
if (main_x3 < cols - 4)
main_x3++;
break;
default: /* TopLeftPane*/
if ((main_x1 < cols - 4) && (main_x2 - main_x1 > 3))
main_x1++;
break;
}
redraw (0);
}
/* ---------------------------------------------------------------------- */
static char *
addr_to_str (char *output, word32 addr)
{ char *name;
int32 delta;
name = syms_val2name (addr, &delta);
if (name[0] != '0')
if (delta)
sprintf (output, "%s+%#lx", name, delta);
else
sprintf (output, "%s", name);
else
sprintf(output,"0x%08lx",addr);
return (output);
}
/* ---------------------------------------------------------------------- */
static void
breakpoint_to_str (char *str, int class, int type, word32 addr,
int length, int count, char *cond)
{ char temp[200];
sprintf (str, "-class %s -type %s -at %s -length %d ",
class == 0 ? "normal" : class == 1 ? "count_down" : "conditional",
type == 0 ? "code" : type == 1 ? "data_write" : "data_read",
addr_to_str (temp, addr),
length
);
if (class == 1)
sprintf (str + strlen (str), "-count %d", count);
if (class == 2)
sprintf (str + strlen (str), "-condition %s", cond);
sprintf (str + strlen (str), "%c\n", 0x0d);
}
/* ---------------------------------------------------------------------- */
static PARSE_DEF bp_def[] = {
{"-class" , STR_TYPE, {0}},
{"-type" , STR_TYPE, {0}},
{"-at" , STR_TYPE, {0}},
{"-length" , INT_TYPE, {0}},
{"-count" , INT_TYPE, {0}},
{"-condition", STR_TYPE, {0}},
{0 , 0 , {0}}
};
/* ---------------------------------------------------------------------- */
static int
str_to_breakpoint (char *str, int *class, int *type, word32 *addr,
int *length, int *count, char *cond)
{ int ok;
char s_class[64], s_type[64], s_addr[128];
s_class[0] = 0; bp_def[0].val.s_val = s_class;
s_type[0] = 0; bp_def[1].val.s_val = s_type;
s_addr[0] = 0; bp_def[2].val.s_val = s_addr;
*length = 4; bp_def[3].val.i_val = length;
*count = 0; bp_def[4].val.i_val = count;
cond[0] = 0; bp_def[5].val.s_val = cond;
parse_string (bp_def, str);
if (stricmp (s_class, "count_down") == 0)
*class = 1;
else if (stricmp (s_class, "conditional") == 0)
*class = 2;
else
*class = 0;
if (stricmp (s_type, "data_write") == 0)
*type = 1;
else if (stricmp (s_type, "data_read") == 0)
*type = 3;
else
*type = 0;
*addr = parse_expression (4, s_addr, &ok);
if (ok != ParseError_ok)
ok = 0;
else
ok = 1;
if (*class == 2 && cond[0] == 0)
ok = 0;
return (ok);
}
/* ---------------------------------------------------------------------- */
static PARSE_DEF reg_def[] = {
{"-number" , STR_TYPE, {0}},
{"-value" , STR_TYPE, {0}},
{0 , 0 , {0}}
};
/* ---------------------------------------------------------------------- */
static int
str_to_reg (char *str, char *index, word32 *addr)
{ int ok;
char s_index[32], s_addr[128];
s_index[0] = 0; reg_def[0].val.s_val = s_index;
s_addr[0] = 0; reg_def[1].val.s_val = s_addr;
parse_string (reg_def, str);
if (s_index[0])
*index = *s_index - '0';
else
return (0);
*addr = parse_expression (4, s_addr, &ok);
if (ok != ParseError_ok)
return (0);
return (1);
}
/* ---------------------------------------------------------------------- */
static PARSE_DEF pa_def[] = {
{"-start" , STR_TYPE, {0}},
{"-stop" , STR_TYPE, {0}},
{0 , 0 , {0}}
};
/* ---------------------------------------------------------------------- */
static int
str_to_pa (char *str, word32 *addr1, word32 *addr2)
{ int ok;
char s_start[128], s_stop[128];
s_start[0] = 0; pa_def[0].val.s_val = s_start;
s_stop[0] = 0; pa_def[1].val.s_val = s_stop;
parse_string (pa_def, str);
*addr1 = parse_expression (4, s_start, &ok);
if (ok != ParseError_ok)
return (0);
*addr2 = parse_expression (4, s_stop, &ok);
if (ok != ParseError_ok)
return (0);
return (1);
}
/* ---------------------------------------------------------------------- */
static PARSE_DEF pane_def[] = {
{"-top_lines" , INT_TYPE, {0}},
{"-top_left_cols", INT_TYPE, {0}},
{"-top_mid_cols" , INT_TYPE, {0}},
{"-bot_left_cols", INT_TYPE, {0}},
{0 , 0 , {0}}
};
/* ---------------------------------------------------------------------- */
static int
str_to_pane (char *str, int *tl, int *x1, int *x2, int *x3)
{ pane_def[0].val.i_val = tl;
pane_def[1].val.i_val = x1;
pane_def[2].val.i_val = x2;
pane_def[3].val.i_val = x3;
parse_string (pane_def, str);
return (1);
}
/* ---------------------------------------------------------------------- */
static int
save_context (int save_bp, int save_reg, int save_pa, int save_pane,
char *filename)
{ FILE *f;
int i;
char temp[200];
f = fopen (filename, "wb");
if (!f)
return (0);
if (save_bp)
{ fputs ("##\015\n", f);
fputs ("# Breakpoint information\015\n", f);
fputs ("##\015\n", f);
fputs (" \015\n", f);
for (i = 0; i < breakpoint_count; i++)
{ sprintf (read_buffer, "bre ");
breakpoint_to_str (read_buffer + strlen (read_buffer),
breakpoint_table[i].sub_type,
breakpoint_table[i].type,
breakpoint_table[i].addr,
breakpoint_table[i].length,
breakpoint_table[i].count,
breakpoint_table[i].condition
);
fputs (read_buffer, f);
}
fputs (" \015\n", f);
}
if (save_reg)
{ fputs ("##\015\n", f);
fputs ("# Debugger registers\015\n", f);
fputs ("##\015\n", f);
fputs (" \015\n", f);
for (i = 0; i < MAX_REGISTERS; i++)
if (registers[i])
{ sprintf (read_buffer, "reg -number %c -value %s\015\n",
i + '0',
addr_to_str (temp, registers[i])
);
fputs (read_buffer, f);
}
fputs (" \015\n", f);
}
if (save_pa)
{ fputs ("##\015\n", f);
fputs ("# Performance Analyzer\015\n", f);
fputs ("##\015\n", f);
fputs (" \015\n", f);
sprintf (read_buffer, "pa -start %s ",
addr_to_str (temp, evaluation_data[0].start_addr)
);
sprintf (read_buffer + strlen (read_buffer), "-stop %s\015\n",
addr_to_str (temp, evaluation_data[EVAL_SEGMENTS - 1].stop_addr)
);
fputs (read_buffer, f);
fputs (" \015\n", f);
}
if (save_pane)
{ fputs ("##\015\n", f);
fputs ("# Pane information\015\n", f);
fputs ("##\015\n", f);
fputs (" \015\n", f);
sprintf (read_buffer,
"pane -top_lines %d -top_left_cols %d -top_mid_cols %d -bot_left_cols %d\015\n",
toplines, main_x1 - 1, main_x2 - main_x1 - 1, main_x3 - 1
);
fputs (read_buffer, f);
fputs (" \015\n", f);
}
fclose (f);
return (1);
}
/* ---------------------------------------------------------------------- */
static int
load_context (int load_bp, int load_reg, int load_pa, int load_pane,
char *filename, int startup_load)
{ FILE *f;
int err, temp;
char command[64];
if (startup_load)
{ f = fopen (startup_file, "rb");
if (!f)
return (0);
} else
{ f = fopen (filename, "rb");
if (!f)
{ message (CL_Error, "Error reading from file %s", filename);
return (0);
}
}
err = load_bp +
((load_reg & 1) << 1) +
((load_pa & 1) << 2) +
((load_pane & 1) << 3);
while (fgets (read_buffer, 1024, f))
{ read_buffer[strlen (read_buffer) - 1] = 0;
if (sscanf (read_buffer, "%s%n", command, &temp) >= 1)
{ if (stricmp (command, "bre") == 0)
{ if (load_bp)
{ int class, type, length, count;
word32 addr;
char cond[200];
count = 0;
cond[0] = 0;
str_to_breakpoint (read_buffer + temp,
&class, &type, &addr, &length, &count, cond);
temp = set_breakpoint (type, length, addr);
breakpoint_table[temp].sub_type = class;
breakpoint_table[temp].count = count;
strcpy (breakpoint_table[temp].condition, cond);
}
err &= ~1;
} else if (stricmp (command, "reg") == 0)
{ if (load_reg)
{ char index;
word32 addr;
if (str_to_reg ((char *)(read_buffer + temp), &index, &addr))
{ registers[(int)index] = addr;
err &= ~2;
}
}
} else if (stricmp (command, "pa") == 0)
{ if (load_pa)
{ word32 addr1, addr2;
if (str_to_pa ((char *)(read_buffer + temp), &addr1, &addr2))
{ init_eval_data (addr1, addr2);
err &= ~4;
}
}
} else if (stricmp (command, "pane") == 0)
{ if (load_pane)
{ int tl = 0, x1 = 0, x2 = 0, x3 = 0;
if (str_to_pane ((char *)(read_buffer + temp), &tl, &x1, &x2, &x3))
{ if (tl < rows - 5 && tl > 3)
{ toplines = tl;
bottomlines = rows - 4 - toplines;
}
if (x1 > 1 && x1 < cols - 5)
{ main_x1 = x1 + 1;
if (main_x2 - main_x1 < 2)
main_x2 = main_x1 + 2;
}
if (x2 > 0 && main_x1 + x2 < cols - 2)
main_x2 = main_x1 + x2 + 1;
if (x3 > 11 + 2 * data_dump_size && main_x3 < cols - 5)
main_x3 = x3 + 1;
err &= ~8;
}
}
}
}
}
fclose (f);
if (startup_load)
return (1);
redraw (0);
if (err)
message (CL_Error, "File has no %s%s%s%s information",
err & 1 ? "breakpoints" : "",
err & 2 ? (err & 1 ? ", registers" : "registers") : "",
err & 4 ? (err & 3 ? ", P.A. data" : "P.A. data") : "",
err & 8 ? (err & 7 ? ", pane layouts" : "pane layouts") : "");
else
message (CL_Info, "Requested context has been successfully loaded.");
return (1);
}
/* ---------------------------------------------------------------------- */
static void
in_ck (char *output, char *input, word32 addr)
{ sprintf (output, "%s", *(int *)addr ? "[X]" : "[ ]");
}
/* ---------------------------------------------------------------------- */
static int
ed_ck (char *text, word32 addr, int x, int y, int len, int *key)
{ if (*key == K_Return || *key == K_Space)/* Only these keys are accepted */
{ if (*(int *)addr)
*(int *)addr = 0;
else
*(int *)addr = 1;
}
*key = 0;
return 1;
}
/* ---------------------------------------------------------------------- */
static void
save_load_context (void)
{ int ret = 7;
static int save_bp = 1, save_reg = 0, save_pa = 0, save_pane = 0;
static char ct_filename[81];
static DIALOG_ITEM dialog_data[] = {
{"Breakpoints :", 0 , 03, 1, format_asis, eval_word, in_ck , ed_ck },
{"Registers :", 0 , 03, 1, format_asis, eval_word, in_ck , ed_ck },
{"Performance Analizer :", 0 , 03, 1, format_asis, eval_word, in_ck , ed_ck },
{"Pane positions :", 0 , 03, 1, format_asis, eval_word, in_ck , ed_ck },
{"Filename :", 0 , 80, 1, format_asis, eval_asis, init_asis, editor},
{0 , 0 , 00 ,0, 0 , 0 , 0 , 0 }
};
static BUTTON_ITEM button_data[] = {
{" Save ", 0, action_done},
{" Load ", 0, action_done},
{" Cancel ", 0, action_done},
{0 , 0, 0 }
};
dialog_data[0].return_addr = (word32)&save_bp;
dialog_data[1].return_addr = (word32)&save_reg;
dialog_data[2].return_addr = (word32)&save_pa;
dialog_data[3].return_addr = (word32)&save_pane;
dialog_data[4].return_addr = (word32)&ct_filename;
dialog ("Debugger Context", dialog_data, button_data, &ret);
switch (ret)
{ case 1:
if (ct_filename[0])
if (save_context (save_bp, save_reg, save_pa, save_pane, ct_filename))
message (CL_Info, "Requested context has been successfully saved.");
else
message (CL_Error, "Error writing to file %s", ct_filename);
break;
case 2:
if (ct_filename[0])
load_context (save_bp, save_reg, save_pa, save_pane, ct_filename, 0);
break;
default:
redraw (0);
}
}
/* ---------------------------------------------------------------------- */
void
debugger (void)
{
int oldpane, lastpane, bar_select, pop_select, command;
static void (*keyhandlers[PANECOUNT])(int) =
{
&code_pane_command, /* 0 */
®ister_pane_command, /* 1 */
&flag_pane_command, /* 2 */
&breakpoint_pane_command, /* 3 */
&data_pane_command, /* 4 */
&npx_pane_command, /* 5 */
&stack_pane_command, /* 6 */
&info_pane_command, /* 7 */
&whereis_pane_command, /* 8 */
&module_pane_command, /* 9 */
&help_pane_command /* 10 */
};
main_entry = syms_name2val ("_main");
first_step = !undefined_symbol;
initialize ();
if (startup_file[0] != 0)
if (load_context (1, 1, 1, 1, startup_file, 1))
message (CL_Info, "Succesfully loaded start-up file %s.", startup_file);
can_longjmp = 1;
setjmp (debugger_jmpbuf);
lastpane = oldpane = -1;
show_menu_bar (Main_Menu);
Main_Menu[0].type = 1;
while (1)
{
int key;
if (pane < 1 || pane > 4)
pane = code_pane_active ? 0
: (npx_pane_active ? 5
: (stack_pane_active ? 6
: (info_pane_active ? 7
: (whereis_pane_active ? 8
: (module_pane_active ? 9
: (help_pane_active ? 10
: (abort (), -1)))))));
if (pane == oldpane)
pane_positions[pane] = pane_pos;
else
{
pane_pos = pane_positions[pane];
lastpane = oldpane;
oldpane = pane;
make_pane_name ();
redraw (0);
if (whereis_pane_active && !whereis_sym_count)
init_whereis_sym ();
}
escaped = 0;
control_c = 0;
control_x = 0;
switch (key = getykey ())
{ case K_Escape:
escaped = 1;
key = getykey ();
break;
case K_Control_C:
control_c = 1;
key = getykey ();
break;
case K_Control_X:
control_x = 1;
key = getykey ();
break;
}
command = 0;
if (escaped)
switch (key)
{ case K_Escape: /* Esc-Esc */
pop_select = 0;
if (!running_xsupport)
{ menu (Main_Menu, &bar_select, &pop_select);
command = bar_select * 100 + pop_select;
} else
{ command = 999;
if (extern_data_support (data_dump_origin +
pane_positions[DATA_PANE_NUM]))
{ running_xsupport = 0;
redraw (0);
}
}
break;
case K_Control_P: /* Esc-^P */
key = getykey ();
command = make_pane_from_key (key);
break;
default:
command = 0;
break;
}
if (control_x)
{ command = 999;
switch (key)
{ case K_Control_C: /* <=> F-Exit */
if (confirm ("Are you sure (y/n)? "))
command = 108;
break;
case K_Control_V: /* <=> F-Context */
command = 107;
break;
case K_Control_W: /* Write Log */
log_current_pane ();
break;
case K_Control_F: /* Read Log */
read_log ();
break;
case K_Control_E: /* <=> M-Evaluate */
command = 402;
break;
case K_Control_X: /* Prev. Reflexive */
if ((lastpane >= 0) && (lastpane < PANECOUNT))
{ command = pane;
pane = lastpane;
lastpane = command;
command = 999;
}
break;
case '^': /* Taller */
current_pane_taller ();
break;
case '}': /* Wider */
current_pane_wider ();
break;
case '<': /* Scroll left */
pane_offset[pane] += SCROLL_COUNT;
redraw (0);
break;
case '>': /* Scroll right */
if (pane_offset[pane] > 0)
pane_offset[pane] -= SCROLL_COUNT;
redraw (0);
break;
case 'm': /* Color / Mono */
case 'M':
if (screen_attr_normal == screen_attr_asm)
command = 105;
else
command = 104;
break;
case 'o':
case 'O': /* Next pane == Tab */
control_x = 0;
key = K_Tab;
break;
default:
command = 0;
break;
}
}
if (control_c)
{ command = 0; /* No command defined*/
}
if (!(escaped || control_x || control_c))
{ command = 999;
switch (key)
{ case K_Tab:
if (pane < 1 || pane > 4)
pane = 1;
else
pane++;
break;
case K_BackTab:
if (pane < 1 || pane > 4)
pane = 4;
else
pane--;
break;
case K_Control_H: /* Global - Help */
command = 207;
break;
case K_Control_R: /* Global - Run */
step (2);
break;
case K_Control_L: /* Global - Refresh */
command = 403;
break;
case K_Control_Z: /* Global - User Scr*/
command = 401;
break;
default:
command = 0;
break;
}
}
switch (command)
{ case 101: /* File - Log */
switch (pane) /* focused pane */
{ case 1: /* Top middle */
read_write_log (main_x1 + 1, 2, main_x2, toplines + 1);
break;
case 2: /* Top right */
read_write_log (main_x2 + 1, 2, cols - 1, toplines + 1);
break;
case 3: /* Bottom right */
read_write_log (main_x3+1, toplines+2, cols-1, rows-1);
break;
case 4: /* Bottom left */
read_write_log (1, toplines + 2, main_x3, rows - 1);
break;
default: /* Top Left */
read_write_log (1, 2, main_x1, toplines + 1);
break;
}
break;
case 102: /* File - Registers */
view_regs ();
break;
case 103: /* File - Resize */
setup_screen ();
break;
case 104: /* File - Mono mode */
init_color (0);
oldpane = -1;
break;
case 105: /* File - Color */
init_color (1);
oldpane = -1;
break;
case 106: /* File - Redirect */
setup_io();
break;
case 107: /* File - Context */
save_load_context ();
break;
case 108: /* File - Exit */
user_screen ();
can_longjmp = 0;
if (using_com_port_num)
com_done();
if (timer_is_set)
reset_timer ();
return;
case 201: /* Pane - Previous */
if (pane < 1 || pane > 4)
pane = 4;
else
pane--;
break;
case 202: /* Pane - Next */
if (pane < 1 || pane > 4)
pane = 1;
else
pane++;
break;
case 203: /* Pane - Data */
pane = 3;
break;
case 205: /* Pane - Breakpoin*/
pane = 4;
break;
case 206: /* Pane - Flags */
pane = 2;
break;
case 211: /* Pane - Registers*/
pane = 1;
break;
case 204: /* Pane - Code */
case 207: /* Pane - Help */
case 208: /* Pane - Info */
case 209: /* Pane - Module */
case 210: /* Pane - Npx */
case 212: /* Pane - Stack */
case 213: /* Pane - Where-is */
code_pane_active = (command == 204);
help_pane_active = (command == 207);
info_pane_active = (command == 208);
module_pane_active = (command == 209);
npx_pane_active = (command == 210);
stack_pane_active = (command == 212);
whereis_pane_active = (command == 213);
pane = 0;
if (npx_pane_active && !has_npx)
{ message (CL_Error, "NPX not present");
npx_pane_active = 0;
code_pane_active = 1;
}
break;
case 214: /* Pane - Resize */
resize_screen();
show_menu_bar (Main_Menu);
oldpane = -1; /* Force redraw. */
break;
case 300: /* Local */
keyhandlers[pane] (0);
break;
case 401: /* Misc - User Scre*/
user_screen ();
(void) getykey ();
debug_screen ();
break;
case 402: /* Misc - Evaluate */
{ int res, ok;
res = read_eval (&ok, "");
if (ok)
message (CL_Msg, "\"%s\" -> %d (0x%08lx)",
read_buffer, res, (word32) res);
break;
}
case 403: /* Misc - Refresh */
re_start_transfer ();
redraw (0);
break;
case 501: /* Help - About */
message (CL_Info,
"Ladybug version %d.%02d", MAJOR_VER, MINOR_VER);
break;
case 502: /* Help - Help */
code_pane_active = 0;
info_pane_active = 0;
module_pane_active = 0;
npx_pane_active = 0;
stack_pane_active = 0;
whereis_pane_active = 0;
help_pane_active = 1;
oldpane = -1; /* Force redraw. */
break;
case 999: /* Executed command*/
break;
default: /* Not global keys */
keyhandlers[pane] (key);
break;
}
}
}
/* ----------------------------------------------------------------------
It's a mystery to me --- the game commences
for the usual fee --- plus expenses
confidential information --- it's in a diary
this is my investigation --- it's not a public inquiry
-- Mark Knopfler, "Private Investigations"
---------------------------------------------------------------------- */